VirtualBox

Ignore:
Timestamp:
Sep 27, 2023 1:34:02 PM (17 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159276
Message:

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

Location:
trunk/src/VBox/Devices/EFI/FirmwareNew
Files:
23 added
10 deleted
96 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/FirmwareNew

  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Application/Cpuid/Cpuid.c

    r99404 r101291  
    22  UEFI Application to display CPUID leaf information.
    33
    4   Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    218218  DisplayFamily = Eax.Bits.FamilyId;
    219219  if (Eax.Bits.FamilyId == 0x0F) {
    220     DisplayFamily |= (Eax.Bits.ExtendedFamilyId << 4);
     220    DisplayFamily += Eax.Bits.ExtendedFamilyId;
    221221  }
    222222
    223223  DisplayModel = Eax.Bits.Model;
    224224  if ((Eax.Bits.FamilyId == 0x06) || (Eax.Bits.FamilyId == 0x0f)) {
    225     DisplayModel |= (Eax.Bits.ExtendedModelId << 4);
     225    DisplayModel += (Eax.Bits.ExtendedModelId << 4);
    226226  }
    227227
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.c

    r99404 r101291  
    22  CPU DXE Module to produce CPU ARCH Protocol.
    33
    4   Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    506506  )
    507507{
    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);
    517518  } 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;
    522540  mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
    523541}
     
    10611079      "%a: %a: add [%Lx, %Lx): %r\n",
    10621080      gEfiCallerBaseName,
    1063       __FUNCTION__,
     1081      __func__,
    10641082      IntersectionBase,
    10651083      IntersectionEnd,
     
    10741092    "with aperture [%Lx, %Lx) cap %Lx\n",
    10751093    gEfiCallerBaseName,
    1076     __FUNCTION__,
     1094    __func__,
    10771095    Descriptor->BaseAddress,
    10781096    Descriptor->BaseAddress + Descriptor->Length,
     
    11151133      "%a: %a: GetMemorySpaceMap(): %r\n",
    11161134      gEfiCallerBaseName,
    1117       __FUNCTION__,
     1135      __func__,
    11181136      Status
    11191137      ));
     
    11981216      "%a: %a: AllocateMemorySpace() Status - %r\n",
    11991217      gEfiCallerBaseName,
    1200       __FUNCTION__,
     1218      __func__,
    12011219      Status
    12021220      ));
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.h

    r99404 r101291  
    22  CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol.
    33
    4   Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1414#include <Protocol/Cpu.h>
    1515#include <Protocol/MpService.h>
     16#include <Register/Intel/Cpuid.h>
    1617#include <Register/Intel/Msr.h>
    1718
     
    2930#include <Library/MtrrLib.h>
    3031#include <Library/LocalApicLib.h>
    31 #include <Library/UefiCpuLib.h>
    3232#include <Library/UefiLib.h>
    3333#include <Library/CpuExceptionHandlerLib.h>
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxe/CpuDxe.inf

    r99404 r101291  
    3434  UefiDriverEntryPoint
    3535  LocalApicLib
    36   UefiCpuLib
    3736  UefiLib
    3837  CpuExceptionHandlerLib
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c

    r99404 r101291  
    297297  )
    298298{
    299   DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __FUNCTION__));
    300   return EFI_SUCCESS;
     299  return RiscVSetMemoryAttributes (BaseAddress, Length, Attributes);
    301300}
    302301
     
    329328  }
    330329
    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));
    332331
    333332  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));
    335334
    336335  InitializeCpuExceptionHandlers (NULL);
     
    340339  //
    341340  DisableInterrupts ();
     341
     342  //
     343  // Enable MMU
     344  //
     345  Status = RiscVConfigureMmu ();
     346  ASSERT_EFI_ERROR (Status);
    342347
    343348  //
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h

    r99404 r101291  
    1616#include <Protocol/RiscVBootProtocol.h>
    1717#include <Library/BaseRiscVSbiLib.h>
     18#include <Library/BaseRiscVMmuLib.h>
    1819#include <Library/BaseLib.h>
    1920#include <Library/CpuExceptionHandlerLib.h>
     
    2122#include <Library/UefiBootServicesTableLib.h>
    2223#include <Library/UefiDriverEntryPoint.h>
     24#include <Register/RiscV64/RiscVEncoding.h>
    2325
    2426/**
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf

    r99404 r101291  
    3838  PeCoffGetEntryPointLib
    3939  RiscVSbiLib
     40  RiscVMmuLib
     41  CacheMaintenanceLib
    4042
    4143[Sources]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuBist.c

    r99404 r101291  
    176176  EFI_SEC_PLATFORM_INFORMATION_CPU      *CpuInstanceInHob;
    177177
    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  }
    179185
    180186  BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) +
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.c

    r99404 r101291  
    474474  }
    475475
    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
    477483  SwitchStackData = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));
    478484  ASSERT (SwitchStackData != NULL);
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.h

    r99404 r101291  
    2929#include <Library/BaseMemoryLib.h>
    3030#include <Library/MemoryAllocationLib.h>
     31#include <Library/CpuPageTableLib.h>
    3132
    3233extern EFI_PEI_PPI_DESCRIPTOR  mPeiCpuMpPpiDesc;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuMpPei.inf

    r89983 r101291  
    4747  CpuLib
    4848  MemoryAllocationLib
     49  CpuPageTableLib
    4950
    5051[Guids]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuMpPei/CpuPaging.c

    r99404 r101291  
    147147
    148148/**
    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 UINTN
    156 GetPhysicalAddressWidth (
    157   VOID
    158   )
    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 /**
    181149  Get the type of top level page table.
    182150
     
    445413
    446414/**
    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**/
     421EFI_STATUS
     422EnablePaePageTable (
    484423  VOID
    485424  )
    486425{
    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;
    557489}
    558490
     
    600532  UINTN                 Bsp;
    601533  UINTN                 Index;
     534  EFI_STATUS            Status;
    602535
    603536  //
     
    609542  }
    610543
    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
    612551  MpInitLibWhoAmI (&Bsp);
    613552  for (Index = 0; Index < NumberOfProcessors; ++Index) {
     
    679618  EDKII_MIGRATED_FV_INFO  *MigratedFvInfo;
    680619  EFI_PEI_HOB_POINTERS    Hob;
     620  IA32_CR0                Cr0;
    681621
    682622  //
     
    692632  }
    693633
    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    }
    696647  }
    697648
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c

    r99404 r101291  
    128128  ASSERT_EFI_ERROR (Status);
    129129
    130   DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));
     130  DEBUG ((DEBUG_VERBOSE, "%a\n", __func__));
    131131  MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
    132132
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf

    r99404 r101291  
    4141  Timer.c
    4242
     43[Pcd]
     44  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
     45
    4346[Protocols]
    4447  gEfiCpuArchProtocolGuid       ## CONSUMES
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/Timer.c

    r99404 r101291  
    1010#include <Library/BaseLib.h>
    1111#include <Library/BaseRiscVSbiLib.h>
     12#include <Library/UefiLib.h>
    1213#include "Timer.h"
    1314
     
    4142// The current period of the timer interrupt
    4243//
    43 STATIC UINT64  mTimerPeriod = 0;
     44STATIC UINT64  mTimerPeriod     = 0;
     45STATIC UINT64  mLastPeriodStart = 0;
    4446
    4547/**
     
    5759{
    5860  EFI_TPL  OriginalTPL;
    59   UINT64   RiscvTimer;
     61  UINT64   PeriodStart;
     62
     63  PeriodStart = RiscVReadTimer ();
    6064
    6165  OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    6266  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      );
    6481  }
    6582
    66   RiscVDisableTimerInterrupt (); // Disable SMode timer int
    67   RiscVClearPendingTimerInterrupt ();
    6883  if (mTimerPeriod == 0) {
     84    RiscVDisableTimerInterrupt ();
    6985    gBS->RestoreTPL (OriginalTPL);
    70     RiscVDisableTimerInterrupt (); // Disable SMode timer int
    7186    return;
    7287  }
    7388
    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
    7699  gBS->RestoreTPL (OriginalTPL);
    77   RiscVEnableTimerInterrupt (); // enable SMode timer int
    78100}
    79101
     
    155177  )
    156178{
    157   UINT64  RiscvTimer;
     179  UINT64  PeriodStart;
    158180
    159181  DEBUG ((DEBUG_INFO, "TimerDriverSetTimerPeriod(0x%lx)\n", TimerPeriod));
     
    165187  }
    166188
    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);
    170201
    171202  mCpu->EnableInterrupt (mCpu);
     
    272303  // Install interrupt handler for RISC-V Timer.
    273304  //
    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                   );
    275310  ASSERT_EFI_ERROR (Status);
    276311
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/CpuTimerDxeRiscV64/Timer.h

    r99404 r101291  
    2222
    2323//
    24 // RISC-V use 100us timer.
     24// RISC-V use 100ns timer.
    2525// The default timer tick duration is set to 10 ms = 10 * 1000 * 10 100 ns units
    2626//
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/CpuPageTableLib.h

    r99404 r101291  
    22  Public include file for PageTableLib library.
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1212typedef union {
    1313  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
    2225
    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
    3030  } Bits;
    3131  UINT64    Uint64;
     
    7575                                 when a new physical base address is set.
    7676  @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.
    7778
    7879  @retval RETURN_UNSUPPORTED        PagingMode is not supported.
    7980  @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.
    8085  @retval RETURN_INVALID_PARAMETER  *BufferSize is not multiple of 4KB.
    8186  @retval RETURN_BUFFER_TOO_SMALL   The buffer is too small for page table creation/updating.
    8287                                    BufferSize is updated to indicate the expected buffer size.
    8388                                    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.
    8590**/
    8691RETURN_STATUS
     
    9499  IN     UINT64              Length,
    95100  IN     IA32_MAP_ATTRIBUTE  *Attribute,
    96   IN     IA32_MAP_ATTRIBUTE  *Mask
     101  IN     IA32_MAP_ATTRIBUTE  *Mask,
     102  OUT    BOOLEAN             *IsModified   OPTIONAL
    97103  );
    98104
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/LocalApicLib.h

    r99404 r101291  
    55  handles cases where local APIC is disabled.
    66
    7   Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
     7  Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
    88  SPDX-License-Identifier: BSD-2-Clause-Patent
    99
     
    184184SendInitIpiAllExcludingSelf (
    185185  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
     197VOID
     198EFIAPI
     199SendStartupIpiAllExcludingSelf (
     200  IN UINT32  StartupRoutine
    186201  );
    187202
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h

    r99404 r101291  
    326326
    327327/**
    328   Read an SMM Save State register on the target processor.  If this function
    329   returns EFI_UNSUPPORTED, then the caller is responsible for reading the
    330   SMM Save Sate register.
    331 
    332   @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
    333                         value must be between 0 and the NumberOfCpus field in
    334                         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 read
    338                         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_STATUS
    346 EFIAPI
    347 SmmCpuFeaturesReadSaveStateRegister (
    348   IN  UINTN                        CpuIndex,
    349   IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
    350   IN  UINTN                        Width,
    351   OUT VOID                         *Buffer
    352   );
    353 
    354 /**
    355   Writes an SMM Save State register on the target processor.  If this function
    356   returns EFI_UNSUPPORTED, then the caller is responsible for writing the
    357   SMM Save Sate register.
    358 
    359   @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
    360                        value must be between 0 and the NumberOfCpus field in
    361                        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_STATUS
    371 EFIAPI
    372 SmmCpuFeaturesWriteSaveStateRegister (
    373   IN UINTN                        CpuIndex,
    374   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    375   IN UINTN                        Width,
    376   IN CONST VOID                   *Buffer
    377   );
    378 
    379 /**
    380328  This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
    381329  notification is completely processed.
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/CpuExceptionHandlerLib.c

    r99404 r101291  
    1212#include <Library/DebugLib.h>
    1313#include <Library/BaseLib.h>
     14#include <Library/SerialPortLib.h>
     15#include <Library/PrintLib.h>
    1416#include <Register/RiscV64/RiscVEncoding.h>
    15 
    1617#include "CpuExceptionHandlerLib.h"
    1718
    18 STATIC EFI_CPU_INTERRUPT_HANDLER  mInterruptHandlers[2];
     19//
     20// Define the maximum message length
     21//
     22#define MAX_DEBUG_MESSAGE_LENGTH  0x100
     23
     24STATIC EFI_CPU_INTERRUPT_HANDLER  mExceptionHandlers[EXCEPT_RISCV_MAX_EXCEPTIONS + 1];
     25STATIC EFI_CPU_INTERRUPT_HANDLER  mIrqHandlers[EXCEPT_RISCV_MAX_IRQS + 1];
     26
     27STATIC CONST CHAR8  mExceptionOrIrqUnknown[]                            = "Unknown";
     28STATIC 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
     55STATIC 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**/
     72STATIC
     73VOID
     74EFIAPI
     75InternalPrintMessage (
     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**/
     103STATIC
     104CONST CHAR8 *
     105GetExceptionNameStr (
     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**/
     131VOID
     132EFIAPI
     133DumpCpuContext (
     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}
    19176
    20177/**
     
    48205
    49206  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 the
    51   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.
    52209  The installed handler is called once for each processor interrupt or exception.
    53210  NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or
    54211  InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned.
    55212
    56   @param[in]  InterruptType     Defines which interrupt or exception to hook.
     213  @param[in]  ExceptionType     Defines which interrupt or exception to hook.
    57214  @param[in]  InterruptHandler  A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
    58215                                when a processor interrupt occurs. If this parameter is NULL, then the handler
     
    60217
    61218  @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 was
     219  @retval EFI_ALREADY_STARTED   InterruptHandler is not NULL, and a handler for ExceptionType was
    63220                                previously installed.
    64   @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
     221  @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for ExceptionType was not
    65222                                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,
    67224                                or this function is not supported.
    68225**/
     
    70227EFIAPI
    71228RegisterCpuInterruptHandler (
    72   IN EFI_EXCEPTION_TYPE         InterruptType,
     229  IN EFI_EXCEPTION_TYPE         ExceptionType,
    73230  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
    74231  )
    75232{
    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
    78260  return EFI_SUCCESS;
    79261}
     
    114296  )
    115297{
    116   UINTN               SCause;
     298  EFI_EXCEPTION_TYPE  ExceptionType;
    117299  EFI_SYSTEM_CONTEXT  RiscVSystemContext;
     300  UINTN               IrqIndex;
    118301
    119302  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  
    6060#define SMODE_TRAP_REGS_sepc     32
    6161#define SMODE_TRAP_REGS_sstatus  33
    62 #define SMODE_TRAP_REGS_sie      34
     62#define SMODE_TRAP_REGS_stval    34
    6363#define SMODE_TRAP_REGS_last     35
    6464
     
    6969typedef struct {
    7070  //
    71   // Below are follow the format of EFI_SYSTEM_CONTEXT
     71  // Below follow the format of EFI_SYSTEM_CONTEXT.
    7272  //
    7373  UINT64    zero;
     
    103103  UINT64    t5;
    104104  UINT64    t6;
    105   //
    106   // Below are the additional information to
    107   // EFI_SYSTEM_CONTEXT, private to supervisor mode trap
    108   // and not public to EFI environment.
    109   //
    110105  UINT64    sepc;
    111106  UINT64    sstatus;
    112   UINT64    sie;
     107  UINT64    stval;
    113108} SMODE_TRAP_REGISTERS;
    114109#pragma pack()
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/SupervisorTrapHandler.S

    r99404 r101291  
    2121
    2222  csrr  t0, CSR_SSTATUS
    23   and   t0, t0, (SSTATUS_SIE | SSTATUS_SPIE)
    2423  sd    t0, SMODE_TRAP_REGS_OFFSET(sstatus)(sp)
    2524  csrr  t0, CSR_SEPC
    2625  sd    t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp)
    27   csrr  t0, CSR_SIE
    28   sd    t0, SMODE_TRAP_REGS_OFFSET(sie)(sp)
     26  csrr  t0, CSR_STVAL
     27  sd    t0, SMODE_TRAP_REGS_OFFSET(stval)(sp)
    2928  ld    t0, SMODE_TRAP_REGS_OFFSET(t0)(sp)
    3029
     30  sd    zero, SMODE_TRAP_REGS_OFFSET(zero)(sp)
    3131  sd    ra, SMODE_TRAP_REGS_OFFSET(ra)(sp)
    3232  sd    gp, SMODE_TRAP_REGS_OFFSET(gp)(sp)
     
    6060
    6161  /* Call to Supervisor mode trap handler in CpuExceptionHandlerLib.c */
     62  mv    a0, sp
    6263  call  RiscVSupervisorModeTrapHandler
    6364
     
    6768  ld    tp, SMODE_TRAP_REGS_OFFSET(tp)(sp)
    6869  ld    t2, SMODE_TRAP_REGS_OFFSET(t2)(sp)
     70  ld    t1, SMODE_TRAP_REGS_OFFSET(t1)(sp)
    6971  ld    s0, SMODE_TRAP_REGS_OFFSET(s0)(sp)
    7072  ld    s1, SMODE_TRAP_REGS_OFFSET(s1)(sp)
     
    9496  ld    t0, SMODE_TRAP_REGS_OFFSET(sepc)(sp)
    9597  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)
    10199  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
    103102  ld    t0, SMODE_TRAP_REGS_OFFSET(t0)(sp)
    104103  addi  sp, sp, SMODE_TRAP_REGS_SIZE
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c

    r99404 r101291  
    2323
    2424**/
     25STATIC
    2526VOID
    2627InternalRiscVTimerDelay (
    27   IN UINT32  Delay
     28  IN UINT64  Delay
    2829  )
    2930{
    30   UINT32  Ticks;
    31   UINT32  Times;
     31  UINT64  Ticks;
    3232
    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  }
    4538}
    4639
     
    6255{
    6356  InternalRiscVTimerDelay (
    64     (UINT32)DivU64x32 (
    65               MultU64x32 (
    66                 MicroSeconds,
    67                 PcdGet64 (PcdCpuCoreCrystalClockFrequency)
    68                 ),
    69               1000000u
    70               )
     57    DivU64x32 (
     58      MultU64x32 (
     59        MicroSeconds,
     60        PcdGet64 (PcdCpuCoreCrystalClockFrequency)
     61        ),
     62      1000000u
     63      )
    7164    );
    7265  return MicroSeconds;
     
    9083{
    9184  InternalRiscVTimerDelay (
    92     (UINT32)DivU64x32 (
    93               MultU64x32 (
    94                 NanoSeconds,
    95                 PcdGet64 (PcdCpuCoreCrystalClockFrequency)
    96                 ),
    97               1000000000u
    98               )
     85    DivU64x32 (
     86      MultU64x32 (
     87        NanoSeconds,
     88        PcdGet64 (PcdCpuCoreCrystalClockFrequency)
     89        ),
     90      1000000000u
     91      )
    9992    );
    10093  return NanoSeconds;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c

    r99404 r101291  
    44  This local APIC library instance supports xAPIC mode only.
    55
    6   Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
     6  Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
    77  Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
    88
     
    2323#include <Library/PcdLib.h>
    2424#include <Library/CpuLib.h>
    25 #include <Library/UefiCpuLib.h>
    2625
    2726//
     
    494493  IcrLow.Uint32                    = 0;
    495494  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**/
     508VOID
     509EFIAPI
     510SendStartupIpiAllExcludingSelf (
     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;
    496522  IcrLow.Bits.Level                = 1;
    497523  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
     
    553579  )
    554580{
    555   LOCAL_APIC_ICR_LOW  IcrLow;
    556 
    557   ASSERT (StartupRoutine < 0x100000);
    558   ASSERT ((StartupRoutine & 0xfff) == 0);
    559 
    560581  SendInitIpiAllExcludingSelf ();
    561582  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);
    568584  if (!StandardSignatureIsAuthenticAMD ()) {
    569585    MicroSecondDelay (200);
    570     SendIpi (IcrLow.Uint32, 0);
     586    SendStartupIpiAllExcludingSelf (StartupRoutine);
    571587  }
    572588}
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf

    r99404 r101291  
    4040  PcdLib
    4141  CpuLib
    42   UefiCpuLib
    4342
    4443[Pcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c

    r99404 r101291  
    55  which have xAPIC and x2APIC modes.
    66
    7   Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
     7  Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
    88  Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
    99
     
    2424#include <Library/PcdLib.h>
    2525#include <Library/CpuLib.h>
    26 #include <Library/UefiCpuLib.h>
    2726#include <IndustryStandard/Tdx.h>
    2827
     
    739738
    740739/**
     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**/
     747VOID
     748EFIAPI
     749SendStartupIpiAllExcludingSelf (
     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/**
    741767  Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
    742768
     
    792818  )
    793819{
    794   LOCAL_APIC_ICR_LOW  IcrLow;
    795 
    796   ASSERT (StartupRoutine < 0x100000);
    797   ASSERT ((StartupRoutine & 0xfff) == 0);
    798 
    799820  SendInitIpiAllExcludingSelf ();
    800821  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);
    807823  if (!StandardSignatureIsAuthenticAMD ()) {
    808824    MicroSecondDelay (200);
    809     SendIpi (IcrLow.Uint32, 0);
     825    SendStartupIpiAllExcludingSelf (StartupRoutine);
    810826  }
    811827}
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf

    r99404 r101291  
    4040  PcdLib
    4141  CpuLib
    42   UefiCpuLib
    4342
    4443[Pcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf

    r85718 r101291  
    55#  Architectures Software Developer's Manual.
    66#
    7 # Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
     7# Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
    88#
    99#  SPDX-License-Identifier: BSD-2-Clause-Patent
     
    5959
    6060[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  
    22  Intel Processor Trace feature.
    33
    4   Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    3434  MSR_IA32_RTIT_OUTPUT_BASE_REGISTER         RtitOutputBase;
    3535  MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER    RtitOutputMaskPtrs;
     36  BOOLEAN                                    CycPacketSupported;
    3637} PROC_TRACE_PROCESSOR_DATA;
    3738
     
    4647
    4748  UINTN                        *TopaMemArray;
     49
     50  BOOLEAN                      EnableOnBspOnly;
     51  BOOLEAN                      EnablePerformanceCollecting;
    4852
    4953  PROC_TRACE_PROCESSOR_DATA    *ProcessorData;
     
    7579  ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *)((UINT8 *)ConfigData + sizeof (PROC_TRACE_DATA));
    7680
    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);
    8086
    8187  return ConfigData;
     
    109115  PROC_TRACE_DATA                              *ProcTraceData;
    110116  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;
    112119
    113120  //
     
    130137  }
    131138
    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);
    135142  if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||
    136143      (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)))
     
    139146    ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64     = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_BASE);
    140147    ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_MASK_PTRS);
     148    ProcTraceData->ProcessorData[ProcessorNumber].CycPacketSupported        = (BOOLEAN)(ProcTraceEbx.Bits.ConfigurablePsb == 1);
     149
    141150    return TRUE;
    142151  }
     
    189198  MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER  OutputMaskPtrsReg;
    190199  RTIT_TOPA_TABLE_ENTRY                    *TopaEntryPtr;
     200  BOOLEAN                                  IsBsp;
    191201
    192202  //
     
    237247  }
    238248
     249  IsBsp = (CpuInfo->ProcessorInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? TRUE : FALSE;
     250
     251  if (ProcTraceData->EnableOnBspOnly && !IsBsp) {
     252    return RETURN_SUCCESS;
     253  }
     254
    239255  MemRegionBaseAddr = 0;
    240256  FirstIn           = FALSE;
     
    261277    //   aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 cleared.
    262278    //
    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;
    284319        }
    285320
    286         break;
     321        ThreadMemRegionTable[Index] = AlignedAddress;
     322        DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64)ThreadMemRegionTable[Index]));
    287323      }
    288324
    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    }
    300335  }
    301336
     
    368403    if (FirstIn) {
    369404      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));
    377457      }
    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;
    405465      }
    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;
    414466    }
    415467
     
    472524  CtrlReg.Bits.BranchEn = 1;
    473525  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
    474542  CPU_REGISTER_TABLE_WRITE64 (
    475543    ProcessorNumber,
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf

    r99404 r101291  
    2929
    3030[Sources.X64]
    31   X64/Xcode5ExceptionHandlerAsm.nasm
     31  X64/ExceptionHandlerAsm.nasm
    3232  X64/ArchExceptionHandler.c
    3333  X64/ArchInterruptDefs.h
     
    6262  DebugLib
    6363  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  
    2929
    3030[Sources.X64]
    31   X64/Xcode5ExceptionHandlerAsm.nasm
     31  X64/SecPeiExceptionHandlerAsm.nasm
    3232  X64/ArchExceptionHandler.c
    3333  X64/ArchInterruptDefs.h
     
    6363  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
    6464
     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  
    2929
    3030[Sources.X64]
    31   X64/ExceptionHandlerAsm.nasm
     31  X64/SecPeiExceptionHandlerAsm.nasm
    3232  X64/ArchExceptionHandler.c
    3333  X64/ArchInterruptDefs.h
     
    5959  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
    6060
     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  
    2929
    3030[Sources.X64]
    31   X64/Xcode5ExceptionHandlerAsm.nasm
     31  X64/ExceptionHandlerAsm.nasm
    3232  X64/ArchExceptionHandler.c
    3333  X64/ArchInterruptDefs.h
     
    6262  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
    6363
     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  
    293293        DEBUG_INFO,
    294294        "%a: Bsp StackBase = 0x%016lx  StackSize = 0x%016lx\n",
    295         __FUNCTION__,
     295        __func__,
    296296        MemoryHob->AllocDescriptor.MemoryBaseAddress,
    297297        MemoryHob->AllocDescriptor.MemoryLength
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm

    r99404 r101291  
    1414;
    1515;------------------------------------------------------------------------------
     16%include "Nasm.inc"
     17
     18;
     19; Equivalent NASM structure of IA32_DESCRIPTOR
     20;
     21struc IA32_DESCRIPTOR
     22  .Limit                         CTYPE_UINT16 1
     23  .Base                          CTYPE_UINTN  1
     24endstruc
     25
     26;
     27; Equivalent NASM structure of IA32_IDT_GATE_DESCRIPTOR
     28;
     29struc 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
     37endstruc
    1638
    1739;
     
    3254ALIGN   8
    3355
    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.
    3657AsmIdtVectorBegin:
    3758%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
    4165    mov     rax, ASM_PFX(CommonInterruptEntry)
     66%endif
    4267    jmp     rax
    4368%assign Vector Vector+1
     
    4671
    4772HookAfterStubHeaderBegin:
    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
     74VectorNum:
     75    push    rax
     76%ifdef NO_ABSOLUTE_RELOCS_IN_TEXT
     77    mov     rax, strict qword 0 ;     mov     rax, HookAfterStubHeaderEnd
     78JmpAbsoluteAddress:
     79%else
    5280    mov     rax, HookAfterStubHeaderEnd
     81%endif
    5382    jmp     rax
    5483HookAfterStubHeaderEnd:
     
    277306    ;
    278307    sub     rsp, 4 * 8 + 8
    279     mov     rax, ASM_PFX(CommonExceptionHandler)
    280     call    rax
     308    call    ASM_PFX(CommonExceptionHandler)
    281309    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
     356CetDone:
    282357
    283358    cli
     
    385460global ASM_PFX(AsmGetTemplateAddressMap)
    386461ASM_PFX(AsmGetTemplateAddressMap):
    387     mov     rax, AsmIdtVectorBegin
     462    lea     rax, [AsmIdtVectorBegin]
    388463    mov     qword [rcx], rax
    389     mov     qword [rcx + 0x8],  (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
    390     mov     rax, HookAfterStubHeaderBegin
     464    mov     qword [rcx + 0x8],  (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256
     465    lea     rax, [HookAfterStubHeaderBegin]
    391466    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
    392482    ret
    393483
     
    398488ASM_PFX(AsmVectorNumFixup):
    399489    mov     rax, rdx
    400     mov     [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
     490    mov     [rcx + (VectorNum - 4 - HookAfterStubHeaderBegin)], al
    401491    ret
    402492
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h

    r99404 r101291  
    22  Internal header for CpuPageTableLib.
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    2020
    2121#define REGION_LENGTH(l)  LShiftU64 (1, (l) * 9 + 3)
     22
     23#define MAX_PAE_PDPTE_NUM  4
    2224
    2325typedef enum {
     
    3032
    3133typedef 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
    3740} IA32_PAGE_COMMON_ENTRY;
    3841
     
    4245typedef union {
    4346  struct {
    44     UINT64    Present              : 1; // 0 = Not present in memory, 1 = Present in memory
    45     UINT64    ReadWrite            : 1; // 0 = Read-Only, 1= Read/Write
    46     UINT64    UserSupervisor       : 1; // 0 = Supervisor, 1=User
    47     UINT64    WriteThrough         : 1; // 0 = Write-Back caching, 1=Write-Through caching
    48     UINT64    CacheDisabled        : 1; // 0 = Cached, 1=Non-Cached
    49     UINT64    Accessed             : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
    50     UINT64    Available0           : 1; // Ignored
    51     UINT64    MustBeZero           : 1; // Must Be Zero
    52 
    53     UINT64    Available2           : 4; // Ignored
    54 
    55     UINT64    PageTableBaseAddress : 40; // Page Table Base Address
    56     UINT64    Available3           : 11; // Ignored
    57     UINT64    Nx                   : 1;  // No Execute bit
     47    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
    5861  } Bits;
    5962  UINT64    Uint64;
     
    8790typedef union {
    8891  struct {
    89     UINT64    Present              : 1; // 0 = Not present in memory, 1 = Present in memory
    90     UINT64    ReadWrite            : 1; // 0 = Read-Only, 1= Read/Write
    91     UINT64    UserSupervisor       : 1; // 0 = Supervisor, 1=User
    92     UINT64    WriteThrough         : 1; // 0 = Write-Back caching, 1=Write-Through caching
    93     UINT64    CacheDisabled        : 1; // 0 = Cached, 1=Non-Cached
    94     UINT64    Accessed             : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
    95     UINT64    Dirty                : 1; // 0 = Not dirty, 1 = Dirty (set by CPU)
    96     UINT64    MustBeOne            : 1; // Page Size. Must Be One
    97 
    98     UINT64    Global               : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1)
    99     UINT64    Available1           : 3; // Ignored
    100     UINT64    Pat                  : 1; // PAT
    101 
    102     UINT64    PageTableBaseAddress : 39; // Page Table Base Address
    103     UINT64    Available3           : 7;  // Ignored
    104     UINT64    ProtectionKey        : 4;  // Protection key
    105     UINT64    Nx                   : 1;  // No Execute bit
     92    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
    106109  } Bits;
    107110  UINT64    Uint64;
     
    124127typedef union {
    125128  struct {
    126     UINT64    Present              : 1; // 0 = Not present in memory, 1 = Present in memory
    127     UINT64    ReadWrite            : 1; // 0 = Read-Only, 1= Read/Write
    128     UINT64    UserSupervisor       : 1; // 0 = Supervisor, 1=User
    129     UINT64    WriteThrough         : 1; // 0 = Write-Back caching, 1=Write-Through caching
    130     UINT64    CacheDisabled        : 1; // 0 = Cached, 1=Non-Cached
    131     UINT64    Accessed             : 1; // 0 = Not accessed, 1 = Accessed (set by CPU)
    132     UINT64    Dirty                : 1; // 0 = Not dirty, 1 = Dirty (set by CPU)
    133     UINT64    Pat                  : 1; // PAT
    134 
    135     UINT64    Global               : 1; // 0 = Not global, 1 = Global (if CR4.PGE = 1)
    136     UINT64    Available1           : 3; // Ignored
    137 
    138     UINT64    PageTableBaseAddress : 40; // Page Table Base Address
    139     UINT64    Available3           : 7;  // Ignored
    140     UINT64    ProtectionKey        : 4;  // Protection key
    141     UINT64    Nx                   : 1;  // No Execute bit
     129    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
    142145  } Bits;
    143146  UINT64    Uint64;
     
    150153typedef union {
    151154  struct {
    152     UINT64    Present              : 1; // 0 = Not present in memory, 1 = Present in memory
    153     UINT64    MustBeZero           : 2; // Must Be Zero
    154     UINT64    WriteThrough         : 1; // 0 = Write-Back caching, 1=Write-Through caching
    155     UINT64    CacheDisabled        : 1; // 0 = Cached, 1=Non-Cached
    156     UINT64    MustBeZero2          : 4; // Must Be Zero
    157 
    158     UINT64    Available            : 3; // Ignored
    159 
    160     UINT64    PageTableBaseAddress : 40; // Page Table Base Address
    161     UINT64    MustBeZero3          : 12; // Must Be Zero
     155    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
    162165  } Bits;
    163166  UINT64    Uint64;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c

    r99404 r101291  
    22  This library implements CpuPageTableLib that are generic for IA32 family CPU.
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    2727  )
    2828{
    29   if (Mask->Bits.PageTableBaseAddress) {
     29  if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) {
    3030    Pte4K->Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (Pte4K->Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_40);
    3131  }
     
    9494  )
    9595{
    96   if (Mask->Bits.PageTableBaseAddress) {
     96  if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) {
    9797    PleB->Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (PleB->Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_39);
    9898  }
     
    203203  }
    204204
    205   Pnle->Bits.Accessed = 0;
     205  Pnle->Bits.Accessed   = 0;
     206  Pnle->Bits.MustBeZero = 0;
    206207
    207208  //
     
    213214  Pnle->Bits.WriteThrough  = 0;
    214215  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**/
     230RETURN_STATUS
     231IsAttributesAndMaskValidForNonPresentEntry (
     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;
    215254}
    216255
     
    236275                                    when a new physical base address is set.
    237276  @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.
    239281  @retval RETURN_SUCCESS            PageTable is created/updated successfully.
    240282**/
     
    252294  IN     UINT64              Offset,
    253295  IN     IA32_MAP_ATTRIBUTE  *Attribute,
    254   IN     IA32_MAP_ATTRIBUTE  *Mask
     296  IN     IA32_MAP_ATTRIBUTE  *Mask,
     297  OUT    BOOLEAN             *IsModified
    255298  )
    256299{
     
    259302  UINTN               Index;
    260303  IA32_PAGING_ENTRY   *PagingEntry;
     304  UINTN               PagingEntryIndex;
     305  UINTN               PagingEntryIndexEnd;
    261306  IA32_PAGING_ENTRY   *CurrentPagingEntry;
    262307  UINT64              RegionLength;
     
    274319  IA32_MAP_ATTRIBUTE  CurrentMask;
    275320  IA32_MAP_ATTRIBUTE  LocalParentAttribute;
     321  UINT64              PhysicalAddrInEntry;
     322  UINT64              PhysicalAddrInAttr;
     323  IA32_PAGING_ENTRY   OriginalParentPagingEntry;
     324  IA32_PAGING_ENTRY   OriginalCurrentPagingEntry;
    276325
    277326  ASSERT (Level != 0);
     
    289338  ParentAttribute             = &LocalParentAttribute;
    290339
     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
    291350  //
    292351  // ParentPagingEntry ONLY is deferenced for checking Present and MustBeOne bits
    293352  // when Modify is FALSE.
    294353  //
    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.
    299357    // 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
    301400    ASSERT (Buffer == NULL || *BufferSize >= SIZE_4KB);
    302401    CreateNew    = TRUE;
     
    304403
    305404    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      }
    348417
    349418      //
     
    352421      //       will make the entire region read-only even the child entries set the RW bit.
    353422      //
     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      //
    354426      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));
    362428    }
    363429  } 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
    364451    //
    365452    // It's a non-leaf entry
     
    376463    //       when PDPTE[0].Nx = 1 but caller wants to map [0-2MB] as Nx = 0 (PDT[0].Nx = 0)
    377464    //            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 
    387465    if ((ParentPagingEntry->Pnle.Bits.ReadWrite == 0) && (Mask->Bits.ReadWrite == 1) && (Attribute->Bits.ReadWrite == 1)) {
    388466      if (Modify) {
     
    418496        // e.g.: Set PDE[0-255].ReadWrite = 0
    419497        //
    420         PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle);
    421498        for (Index = 0; Index < 512; Index++) {
    422499          if (PagingEntry[Index].Pce.Present == 0) {
     
    435512
    436513  //
    437   // RegionLength: 256T (1 << 48) 512G (1 << 39), 1G (1 << 30), 2M (1 << 21) or 4K (1 << 12).
    438514  // RegionStart:  points to the linear address that's aligned on RegionLength and lower than (LinearAddress + Offset).
    439515  //
    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;
    446518  ParentAttribute->Uint64 = PageTableLibGetPnleMapAttribute (&ParentPagingEntry->Pnle, ParentAttribute);
    447519
     
    492564        }
    493565
     566        //
     567        // Check if any leaf PagingEntry is modified.
     568        //
     569        OriginalCurrentPagingEntry.Uint64 = CurrentPagingEntry->Uint64;
    494570        PageTableLibSetPle (Level, CurrentPagingEntry, Offset, Attribute, &CurrentMask);
     571
     572        if (OriginalCurrentPagingEntry.Uint64 != CurrentPagingEntry->Uint64) {
     573          *IsModified = TRUE;
     574        }
    495575      }
    496576    } else {
     
    515595                 Offset,
    516596                 Attribute,
    517                  Mask
     597                 Mask,
     598                 IsModified
    518599                 );
    519600      if (RETURN_ERROR (Status)) {
     
    525606    RegionStart += RegionLength;
    526607    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;
    527616  }
    528617
     
    547636                                 when a new physical base address is set.
    548637  @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.
    549639
    550640  @retval RETURN_UNSUPPORTED        PagingMode is not supported.
    551641  @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.
    552646  @retval RETURN_INVALID_PARAMETER  *BufferSize is not multiple of 4KB.
    553647  @retval RETURN_BUFFER_TOO_SMALL   The buffer is too small for page table creation/updating.
    554648                                    BufferSize is updated to indicate the expected buffer size.
    555649                                    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.
    557651**/
    558652RETURN_STATUS
     
    566660  IN     UINT64              Length,
    567661  IN     IA32_MAP_ATTRIBUTE  *Attribute,
    568   IN     IA32_MAP_ATTRIBUTE  *Mask
     662  IN     IA32_MAP_ATTRIBUTE  *Mask,
     663  OUT    BOOLEAN             *IsModified   OPTIONAL
    569664  )
    570665{
     
    576671  IA32_PAGE_LEVEL     MaxLeafLevel;
    577672  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)) {
    580683    //
    581684    // 32bit paging is never supported.
    582     // PAE paging will be supported later.
    583685    //
    584686    return RETURN_UNSUPPORTED;
     
    596698  }
    597699
    598   if ((LinearAddress % SIZE_4KB != 0) || (Length % SIZE_4KB != 0)) {
     700  if (((UINTN)LinearAddress % SIZE_4KB != 0) || ((UINTN)Length % SIZE_4KB != 0)) {
    599701    //
    600702    // LinearAddress and Length should be multiple of 4K.
     
    607709  }
    608710
     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
    609719  MaxLeafLevel     = (IA32_PAGE_LEVEL)(UINT8)PagingMode;
    610720  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);
    612722
    613723  if ((LinearAddress > MaxLinearAddress) || (Length > MaxLinearAddress - LinearAddress)) {
    614724    //
    615     // Maximum linear address is (1 << 48) or (1 << 57)
     725    // Maximum linear address is (1 << 32), (1 << 48) or (1 << 57)
    616726    //
    617727    return RETURN_INVALID_PARAMETER;
     
    620730  TopPagingEntry.Uintn = *PageTable;
    621731  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
    622747    TopPagingEntry.Pce.Present        = 1;
    623748    TopPagingEntry.Pce.ReadWrite      = 1;
     
    626751  }
    627752
    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;
    634765
    635766  //
     
    649780                   0,
    650781                   Attribute,
    651                    Mask
     782                   Mask,
     783                   IsModified
    652784                   );
     785  ASSERT (*IsModified == FALSE);
    653786  if (RETURN_ERROR (Status)) {
    654787    return Status;
     
    681814             0,
    682815             Attribute,
    683              Mask
     816             Mask,
     817             IsModified
    684818             );
     819
    685820  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    }
    687848  }
    688849
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c

    r99404 r101291  
    22  This library implements CpuPageTableLib that are generic for IA32 family CPU.
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    159159  IN     UINT64              PageTableBaseAddress,
    160160  IN     UINTN               Level,
     161  IN     UINTN               MaxLevel,
    161162  IN     UINT64              RegionStart,
    162163  IN     IA32_MAP_ATTRIBUTE  *ParentMapAttribute,
     
    172173  IA32_MAP_ATTRIBUTE  MapAttribute;
    173174  UINT64              RegionLength;
     175  UINTN               PagingEntryNumber;
    174176
    175177  ASSERT (OneEntry != NULL);
    176178
    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) {
    181184    if (PagingEntry[Index].Pce.Present == 0) {
    182185      continue;
     
    229232        IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry[Index].Pnle),
    230233        Level - 1,
     234        MaxLevel,
    231235        RegionStart,
    232236        &MapAttribute,
     
    270274  IA32_MAP_ENTRY      OneEntry;
    271275  UINTN               MaxLevel;
     276  UINTN               Index;
     277  IA32_PAGING_ENTRY   BufferInStack[MAX_PAE_PDPTE_NUM];
    272278
    273279  if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
     
    289295    *MapCount = 0;
    290296    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;
    291308  }
    292309
     
    320337  *MapCount   = 0;
    321338  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);
    323340
    324341  if (*MapCount > MapCapacity) {
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/CpuPageTableLibUnitTestHost.c

    r99404 r101291  
    22  Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1010
    1111// ----------------------------------------------------------------------- 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 };
    1617
    1718/**
     
    5253  // If the input linear address is not 4K align, it should return invalid parameter
    5354  //
    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);
    5556
    5657  //
     
    5859  //
    5960  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);
    6162
    6263  //
     
    6566  PageTableBufferSize = 0;
    6667  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);
    6869
    6970  //
     
    7172  //
    7273  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);
    7475
    7576  return UNIT_TEST_PASSED;
     
    120121  // Create page table to cover [0, 10M], it should have 5 PTE
    121122  //
    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);
    123124  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    124125  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);
    126127  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    127128  TestStatus = IsPageTableValid (PageTable, PagingMode);
     
    135136  //
    136137  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);
    138139  UT_ASSERT_EQUAL (PageTableBufferSize, 0);
    139140  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
     
    149150  MapMask.Bits.Nx     = 0;
    150151  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);
    152153  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    153154  UT_ASSERT_EQUAL (PageTableBufferSize, 0);
     
    165166  MapMask.Bits.Accessed      = 1;
    166167  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);
    168169  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    169170  UT_ASSERT_EQUAL (PageTableBufferSize, 0);
     
    218219  MapMask.Bits.Present      = 1;
    219220  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);
    221222  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    222223  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);
    224225  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    225226
     
    282283  // Create Page table to cover [0,2G], with ReadWrite = 1
    283284  //
    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);
    285286  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    286287  BackupPageTableBufferSize = PageTableBufferSize;
    287288  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);
    289290  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    290291  IsPageTableValid (PageTable, PagingMode);
     
    332333  //
    333334  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);
    335336  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    336337  IsPageTableValid (PageTable, PagingMode);
     
    361362  MapAttribute.Bits.ReadWrite = 1;
    362363  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);
    364365  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    365366  IsPageTableValid (PageTable, PagingMode);
     
    423424  IA32_PAGING_ENTRY   *PagingEntry;
    424425
    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;
    434434  //
    435435  // Create Page table to cover [2M-4K, 4M], with ReadWrite = 1
    436436  //
    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);
    438438  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    439439  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);
    441441  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    442442  IsPageTableValid (PageTable, PagingMode);
     
    461461  // [2M   ,4M], R/W = 1
    462462  //
    463   PagingEntry         = (IA32_PAGING_ENTRY *)(UINTN)PageTable;                                           // Get 4 level entry
    464   PagingEntry         = (IA32_PAGING_ENTRY *)(UINTN)(PagingEntry->Pnle.Bits.PageTableBaseAddress << 12); // Get 3 level entry
    465   PagingEntry         = (IA32_PAGING_ENTRY *)(UINTN)(PagingEntry->Pnle.Bits.PageTableBaseAddress << 12); // Get 2 level entry
     463  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
    466466  PagingEntry->Uint64 = PagingEntry->Uint64 & (~(UINT64)0x2);
    467467  MapCount            = 0;
     
    481481  UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2MB);
    482482  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;
    486485  UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64);
    487486
     
    490489  // Just need to set [2M-4K,2M], won't need extra size, so the status should be success
    491490  //
    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);
    497496  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    498497  return UNIT_TEST_PASSED;
     
    541540  // Create Page table to cover [0,4M], and [4M, 1G] is not present
    542541  //
    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);
    544543  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    545544  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);
    547546  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    548547  TestStatus = IsPageTableValid (PageTable, PagingMode);
     
    556555  //
    557556  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);
    559558  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    560559  TestStatus = IsPageTableValid (PageTable, PagingMode);
     
    565564  MapAttribute.Bits.Accessed = 1;
    566565  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);
    568567  //
    569568  // 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
     
    620619  // Create Page table to cover [0,2G], with Nx = 0
    621620  //
    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);
    623622  UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    624623  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);
    626625  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    627626  TestStatus = IsPageTableValid (PageTable, PagingMode);
     
    667666  // Call library to change Nx to 0 for [0,1G]
    668667  //
    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);
    670669  UT_ASSERT_EQUAL (Status, RETURN_SUCCESS);
    671670  TestStatus = IsPageTableValid (PageTable, PagingMode);
     
    699698
    700699/**
     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**/
     715UNIT_TEST_STATUS
     716EFIAPI
     717TestCaseToCheckMapMaskAndAttr (
     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/**
    701825  Initialize the unit test framework, suite, and unit tests for the
    702826  sample unit tests and run the unit tests.
     
    747871  AddTestCase (ManualTestCase, "Check if the parent entry has different Nx attribute", "Manual Test Case6", TestCaseManualChangeNx, NULL, NULL, NULL);
    748872  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);
    750874  //
    751875  // Populate the Random Test Cases.
     
    758882  }
    759883
    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);
    764889
    765890  //
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c

    r99404 r101291  
    22  Random test case for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    8383
    8484/**
    85   Return a random boolean.
    86 
    87   @return boolean
    88 **/
    89 BOOLEAN
    90 RandomBoolean (
    91   VOID
    92   )
    93 {
    94   BOOLEAN  Value;
    95 
    96   LocalRandomBytes ((UINT8 *)&Value, sizeof (BOOLEAN));
    97   return Value%2;
    98 }
    99 
    100 /**
    10185  Return a 32bit random number.
    10286
     
    138122
    139123  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**/
     133BOOLEAN
     134RandomBoolean (
     135  UINT8  Probability
     136  )
     137{
     138  return ((Probability > ((UINT8)Random64 (0, 100))) ? TRUE : FALSE);
    140139}
    141140
     
    159158{
    160159  UINT64             Index;
    161   UINT64             TempPhysicalBase;
     160  UINT32             PageTableBaseAddressLow;
     161  UINT32             PageTableBaseAddressHigh;
    162162  IA32_PAGING_ENTRY  *ChildPageEntry;
    163163  UNIT_TEST_STATUS   Status;
     
    179179    }
    180180
    181     if ((RandomNumber < 100) && RandomBoolean ()) {
     181    if ((RandomNumber < 100) && RandomBoolean (50)) {
    182182      RandomNumber++;
    183183      if (Level == 1) {
    184         TempPhysicalBase = PagingEntry->Pte4K.Bits.PageTableBaseAddress;
     184        PageTableBaseAddressLow  = PagingEntry->Pte4K.Bits.PageTableBaseAddressLow;
     185        PageTableBaseAddressHigh = PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh;
    185186      } else {
    186         TempPhysicalBase = PagingEntry->PleB.Bits.PageTableBaseAddress;
     187        PageTableBaseAddressLow  = PagingEntry->PleB.Bits.PageTableBaseAddressLow;
     188        PageTableBaseAddressHigh = PagingEntry->PleB.Bits.PageTableBaseAddressHigh;
    187189      }
    188190
     
    190192      PagingEntry->Pte4K.Bits.Present = 1;
    191193      if (Level == 1) {
    192         PagingEntry->Pte4K.Bits.PageTableBaseAddress = TempPhysicalBase;
     194        PagingEntry->Pte4K.Bits.PageTableBaseAddressLow  = PageTableBaseAddressLow;
     195        PagingEntry->Pte4K.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh;
    193196      } else {
    194         PagingEntry->PleB.Bits.PageTableBaseAddress = TempPhysicalBase;
     197        PagingEntry->PleB.Bits.PageTableBaseAddressLow  = PageTableBaseAddressLow;
     198        PagingEntry->PleB.Bits.PageTableBaseAddressHigh = PageTableBaseAddressHigh;
    195199      }
    196200
     
    212216  }
    213217
    214   if ((RandomNumber < 100) && RandomBoolean ()) {
     218  if ((RandomNumber < 100) && RandomBoolean (50)) {
    215219    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;
    221227    ASSERT ((PagingEntry->Uint64 & mValidMaskLeafFlag[Level].Uint64) != mValidMaskLeafFlag[Level].Uint64);
    222228  }
    223229
    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));
    225231  for (Index = 0; Index < 512; Index++) {
    226232    Status = ValidateAndRandomeModifyPageTablePageTableEntry (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3)));
     
    253259  IA32_PAGING_ENTRY  *PagingEntry;
    254260
    255   if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {
     261  if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
    256262    //
    257263    // 32bit paging is never supported.
    258     // PAE paging will be supported later.
    259264    //
    260265    return UNIT_TEST_ERROR_TEST_FAILED;
     
    276281
    277282/**
     283  Remove the last MAP_ENTRY in MapEntrys.
     284
     285  @param MapEntrys   Pointer to MapEntrys buffer
     286**/
     287VOID
     288RemoveLastMapEntry (
     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/**
    278304  Generate single random map entry.
    279305  The map entry can be the input of function PageTableMap
     
    300326  // use AlignedTable to avoid that a random number can be very hard to be 1G or 2M aligned
    301327  //
    302   if ((MapsIndex != 0) &&  (RandomBoolean ())) {
     328  if ((MapsIndex != 0) &&  (RandomBoolean (50))) {
    303329    FormerLinearAddress = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].LinearAddress;
    304330    if (FormerLinearAddress < 2 * (UINT64)SIZE_1GB) {
     
    324350  MapEntrys->Maps[MapsIndex].Length = Random64 (0, MIN (MaxAddress - MapEntrys->Maps[MapsIndex].LinearAddress, 10 * (UINT64)SIZE_1GB)) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)];
    325351
    326   if ((MapsIndex != 0)  && (RandomBoolean ())) {
     352  if ((MapsIndex != 0)  && (RandomBoolean (50))) {
    327353    MapEntrys->Maps[MapsIndex].Attribute.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Attribute.Uint64;
    328354    MapEntrys->Maps[MapsIndex].Mask.Uint64      = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64;
    329355  } else {
    330356    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
    332367    if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) {
    333368      MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF;
     
    336371
    337372  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;
    340376  } 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)]);
    350379  }
    351380
     
    394423  for (Index = 0; Index < MapCount; Index++) {
    395424    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;
    398428      break;
    399429    }
     
    405435  for (Index = 0; Index < InitMapCount; Index++) {
    406436    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
    409441      break;
    410442    }
     
    423455      AttributeInMapEntrys.Uint64 &= (~MapEntrys->Maps[Index].Mask.Uint64);
    424456      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;
    427460      }
    428461    }
     
    438471    DEBUG ((DEBUG_INFO, "======detailed information begin=====\n"));
    439472    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)));
    442475    DEBUG ((DEBUG_INFO, "The total Mask is 0x%lx\n", MaskInMapEntrys.Uint64));
    443476
     
    610643  )
    611644{
    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;
    627672
    628673  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  }
    629708
    630709  PageTableBufferSize = 0;
     
    634713                          NULL,
    635714                          &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
    640720                          );
     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
    641762  if (PageTableBufferSize != 0) {
    642763    UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
     
    653774               Buffer,
    654775               &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
    659781               );
    660782  }
     
    670792  }
    671793
    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) {
    675797    UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
    676798
    677799    //
    678     // Allocate memory for Maps
     800    // Allocate memory for Map2
    679801    // Note the memory is only used in this one Single MapEntry Test
    680802    //
    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    }
    684819  }
    685820
     
    691826  //
    692827  KeyPointCount = 0;
    693   GetKeyPointList (MapEntrys, Map, MapCount, NULL, &KeyPointCount);
     828  GetKeyPointList (MapEntrys, Map2, MapCount2, NULL, &KeyPointCount);
    694829  KeyPointBuffer = AllocatePages (EFI_SIZE_TO_PAGES (KeyPointCount * sizeof (UINT64)));
    695830  ASSERT (KeyPointBuffer != NULL);
    696831  NewKeyPointCount = 0;
    697   GetKeyPointList (MapEntrys, Map, MapCount, KeyPointBuffer, &NewKeyPointCount);
     832  GetKeyPointList (MapEntrys, Map2, MapCount2, KeyPointBuffer, &NewKeyPointCount);
    698833
    699834  //
     
    701836  //
    702837  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)) {
    704839      DEBUG ((DEBUG_INFO, "Error happens at below key point\n"));
    705840      DEBUG ((DEBUG_INFO, "Index = %d KeyPointBuffer[Index] = 0x%lx\n", Index, KeyPointBuffer[Index]));
     
    713848  if (MapCount != 0) {
    714849    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)));
    715854  }
    716855
     
    8901029  UT_ASSERT_TRUE ((Random32 (9, 10) >= 9) & (Random32 (9, 10) <= 10));
    8911030  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;
    9071043
    9081044  mRandomOption = ((CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT *)Context)->RandomOption;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c

    r99404 r101291  
    22  helper file for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
    33
    4   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    141141  }
    142142
    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));
    144144  for (Index = 0; Index < 512; Index++) {
    145145    Status = IsPageTableEntryValid (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3)));
     
    172172  IA32_PAGING_ENTRY  *PagingEntry;
    173173
    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)) {
    175179    //
    176180    // 32bit paging is never supported.
    177     // PAE paging will be supported later.
    178181    //
    179182    return UNIT_TEST_ERROR_TEST_FAILED;
     
    184187
    185188  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
    187195    Status = IsPageTableEntryValid (&PagingEntry[Index], MaxLevel, MaxLeafLevel, Index << (9 * MaxLevel + 3));
    188196    if (Status != UNIT_TEST_PASSED) {
     
    230238  // Not a leaf
    231239  //
    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));
    233241  *Level         = *Level -1;
    234242  Index          = Address >> (*Level * 9 + 3);
     
    261269  IA32_PAGING_ENTRY  *PagingEntry;
    262270
    263   if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {
     271  if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
    264272    //
    265273    // 32bit paging is never supported.
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/AmdSev.c

    r99404 r101291  
    261261  }
    262262}
     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**/
     269VOID
     270AmdSevUpdateCpuMpData (
     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  
    22#  MP Initialize Library instance for DXE driver.
    33#
    4 #  Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
     4#  Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
    55#  SPDX-License-Identifier: BSD-2-Clause-Patent
    66#
     
    2525  Ia32/AmdSev.c
    2626  Ia32/MpFuncs.nasm
     27  Ia32/CreatePageTable.c
    2728
    2829[Sources.X64]
    2930  X64/AmdSev.c
    3031  X64/MpFuncs.nasm
     32  X64/CreatePageTable.c
    3133
    3234[Sources.common]
     
    3739  MpLib.h
    3840  Microcode.c
     41  MpHandOff.h
    3942
    4043[Packages]
     
    5053  MtrrLib
    5154  CpuLib
    52   UefiCpuLib
    5355  UefiBootServicesTableLib
    5456  DebugAgentLib
     
    5759  CcExitLib
    5860  MicrocodeLib
     61[LibraryClasses.X64]
     62  CpuPageTableLib
    5963
    6064[Protocols]
     
    7882  gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures                  ## CONSUMES
    7983  gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase                       ## SOMETIMES_CONSUMES
     84  gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi                ## CONSUMES
    8085  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard                      ## CONSUMES
    8186  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase                           ## CONSUMES
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c

    r99404 r101291  
    22  MP initialize support functions for DXE phase.
    33
    4   Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    2121#define  AP_SAFE_STACK_SIZE  128
    2222
    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;
     23CPU_MP_DATA             *mCpuMpData                  = NULL;
     24EFI_EVENT               mCheckAllApsEvent            = NULL;
     25EFI_EVENT               mMpInitExitBootServicesEvent = NULL;
     26EFI_EVENT               mLegacyBootEvent             = NULL;
     27volatile BOOLEAN        mStopCheckAllApsStatus       = TRUE;
     28RELOCATE_AP_LOOP_ENTRY  mReservedApLoop;
     29UINTN                   mReservedTopOfApStack;
     30volatile UINT32         mNumberToFinish = 0;
     31UINTN                   mApPageTable;
    3132
    3233//
     
    379380  )
    380381{
    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;
    386386
    387387  MpInitLibWhoAmI (&ProcessorNumber);
     
    389389  MwaitSupport = IsMwaitSupport ();
    390390  if (CpuMpData->UseSevEsAPMethod) {
     391    //
     392    // 64-bit AMD processors with SEV-ES
     393    //
    391394    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                      );
    392405  } else {
     406    //
     407    // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
     408    //
    393409    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
    407419  //
    408420  // It should never reach here
     
    452464  }
    453465
    454   DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__));
     466  DEBUG ((DEBUG_INFO, "%a() done!\n", __func__));
    455467}
    456468
     
    467479  EFI_STATUS                       Status;
    468480  EFI_PHYSICAL_ADDRESS             Address;
    469   UINTN                            ApSafeBufferSize;
    470481  UINTN                            Index;
    471482  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  MemDesc;
    472483  UINTN                            StackBase;
    473484  CPU_INFO_IN_HOB                  *CpuInfoInHob;
     485  MP_ASSEMBLY_ADDRESS_MAP          *AddressMap;
     486  UINT8                            *ApLoopFunc;
     487  UINTN                            ApLoopFuncSize;
     488  UINTN                            StackPages;
     489  UINTN                            FuncPages;
    474490
    475491  SaveCpuMpData (CpuMpData);
     
    526542  }
    527543
     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
    528561  //
    529562  // Avoid APs access invalid buffer data which allocated by BootServices,
     
    534567  // Exit Boot Services callback function.
    535568  //
    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                  );
    548587  ASSERT_EFI_ERROR (Status);
    549 
    550   mReservedApLoopFunc = (VOID *)(UINTN)Address;
    551   ASSERT (mReservedApLoopFunc != NULL);
    552588
    553589  //
     
    562598    gDS->SetMemorySpaceAttributes (
    563599           Address,
    564            ApSafeBufferSize,
     600           EFI_PAGES_TO_SIZE (FuncPages),
    565601           MemDesc.Attributes & (~EFI_MEMORY_XP)
    566602           );
    567603  }
    568604
    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);
    584606  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  }
    590619
    591620  Status = gBS->CreateEvent (
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm

    r99404 r101291  
    11;------------------------------------------------------------------------------ ;
    2 ; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
     2; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    33; SPDX-License-Identifier: BSD-2-Clause-Patent
    44;
     
    198198    push       ebx               ; Push ApIndex
    199199    mov        eax, esi
    200     add        eax, MP_CPU_EXCHANGE_INFO_OFFSET
    201     push       eax               ; push address of exchange info data buffer
     200    add        eax, MP_CPU_EXCHANGE_INFO_FIELD (CpuMpData)
     201    push       dword [eax]       ; push address of CpuMpData
    202202
    203203    mov        edi, esi
     
    220220
    221221;-------------------------------------------------------------------------------------
    222 ;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
     222;  AsmRelocateApLoopGeneric (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
    223223;
    224224;  The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are
    225225;  specific to SEV-ES support and are not applicable on IA32.
    226226;-------------------------------------------------------------------------------------
    227 AsmRelocateApLoopStart:
     227AsmRelocateApLoopGenericStart:
    228228    mov        eax, esp
    229     mov        esp, [eax + 16]     ; TopOfApStack
     229    mov        esp, [eax + 12]     ; TopOfApStack
    230230    push       dword [eax]         ; push return address for stack trace
    231231    push       ebp
     
    233233    mov        ebx, [eax + 8]      ; ApTargetCState
    234234    mov        ecx, [eax + 4]      ; MwaitSupport
    235     mov        eax, [eax + 20]     ; CountTofinish
     235    mov        eax, [eax + 16]     ; CountTofinish
    236236    lock dec   dword [eax]         ; (*CountTofinish)--
    237237    cmp        cl,  1              ; Check mwait-monitor support
    238     jnz        HltLoop
    239 MwaitLoop:
     238    jnz        HltLoopGeneric
     239MwaitLoopGeneric:
    240240    cli
    241241    mov        eax, esp
     
    246246    shl        eax, 4
    247247    mwait
    248     jmp        MwaitLoop
    249 HltLoop:
     248    jmp        MwaitLoopGeneric
     249HltLoopGeneric:
    250250    cli
    251251    hlt
    252     jmp        HltLoop
    253 AsmRelocateApLoopEnd:
     252    jmp        HltLoopGeneric
     253AsmRelocateApLoopGenericEnd:
    254254
    255255;-------------------------------------------------------------------------------------
     
    265265    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart
    266266    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
    267     mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], AsmRelocateApLoopStart
    268     mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
     267    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], AsmRelocateApLoopGenericStart
     268    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart
    269269    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
    270270    mov        dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/Microcode.c

    r99404 r101291  
    171171    DEBUG_INFO,
    172172    "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
    173     __FUNCTION__,
     173    __func__,
    174174    CpuMpData->MicrocodePatchAddress,
    175175    CpuMpData->MicrocodePatchRegionSize
     
    306306      DEBUG_INFO,
    307307      "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
    308       __FUNCTION__,
     308      __func__,
    309309      PatchCount,
    310310      TotalLoadSize
     
    366366  GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid);
    367367  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__));
    369369    return FALSE;
    370370  }
     
    378378    DEBUG_INFO,
    379379    "%a: MicrocodeBase = 0x%lx, MicrocodeSize = 0x%lx\n",
    380     __FUNCTION__,
     380    __func__,
    381381    *Address,
    382382    *RegionSize
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpEqu.inc

    r99404 r101291  
    11;------------------------------------------------------------------------------ ;
    2 ; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
     2; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    33; SPDX-License-Identifier: BSD-2-Clause-Patent
    44;
     
    2222;
    2323struc 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
    3335endstruc
    3436
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpLib.c

    r99404 r101291  
    1919
    2020EFI_GUID  mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
     21EFI_GUID  mMpHandOffGuid       = MP_HANDOFF_GUID;
    2122
    2223/**
     
    669670
    670671/**
     672  This function place APs in Halt loop.
     673
     674  @param[in] CpuMpData        Pointer to CPU MP Data
     675**/
     676VOID
     677PlaceAPInHltLoop (
     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**/
     700VOID
     701PlaceAPInMwaitLoopOrRunLoop (
     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/**
    671742  This function will be called from AP reset code if BSP uses WakeUpAP.
    672743
    673   @param[in] ExchangeInfo     Pointer to the MP exchange info buffer
     744  @param[in] CpuMpData        Pointer to CPU MP Data
    674745  @param[in] ApIndex          Number of current executing AP
    675746**/
     
    677748EFIAPI
    678749ApWakeupFunction (
    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{
    684754  UINTN             ProcessorNumber;
    685755  EFI_AP_PROCEDURE  Procedure;
     
    691761  UINTN             CurrentApicMode;
    692762  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;
    698764
    699765  //
     
    736802      //
    737803      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
    738813      InterlockedCompareExchange32 (
    739814        (UINT32 *)ApStartupSignalBuffer,
     
    844919    //
    845920    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**/
     938VOID
     939EFIAPI
     940DxeApEntryPoint (
     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);
    894955}
    895956
     
    12651326        SevSnpCreateAP (CpuMpData, -1);
    12661327      } 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        }
    12681336      }
    12691337    }
     
    14651533
    14661534/**
     1535  Switch Context for each AP.
     1536
     1537**/
     1538VOID
     1539EFIAPI
     1540SwitchContextPerAp (
     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/**
    14671561  Checks whether timeout expires.
    14681562
     
    15691663      DEBUG_VERBOSE,
    15701664      "%a: reached FinishedApLimit=%u in %Lu microseconds\n",
    1571       __FUNCTION__,
     1665      __func__,
    15721666      FinishedApLimit,
    15731667      DivU64x64Remainder (
     
    18171911
    18181912/**
     1913  This function Get BspNumber.
     1914
     1915  @param[in] MpHandOff        Pointer to MpHandOff
     1916  @return                     BspNumber
     1917**/
     1918UINT32
     1919GetBspNumber (
     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**/
     1954VOID
     1955SwitchApContext (
     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**/
     1986MP_HAND_OFF *
     1987GetMpHandOffHob (
     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/**
    18192004  MP Initialize Library initialization.
    18202005
     
    18352020  )
    18362021{
    1837   CPU_MP_DATA              *OldCpuMpData;
     2022  MP_HAND_OFF              *MpHandOff;
    18382023  CPU_INFO_IN_HOB          *CpuInfoInHob;
    18392024  UINT32                   MaxLogicalProcessorNumber;
     
    18542039  UINTN                    ApIdtBase;
    18552040
    1856   OldCpuMpData = GetCpuMpDataFromGuidedHob ();
    1857   if (OldCpuMpData == NULL) {
     2041  MpHandOff = GetMpHandOffHob ();
     2042  if (MpHandOff == NULL) {
    18582043    MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
    18592044  } else {
    1860     MaxLogicalProcessorNumber = OldCpuMpData->CpuCount;
     2045    MaxLogicalProcessorNumber = MpHandOff->CpuCount;
    18612046  }
    18622047
     
    20022187  ProgramVirtualWireMode ();
    20032188
    2004   if (OldCpuMpData == NULL) {
     2189  if (MpHandOff == NULL) {
    20052190    if (MaxLogicalProcessorNumber > 1) {
    20062191      //
     
    20142199    // from HOB
    20152200    //
    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;
    20212208    for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
    20222209      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;
    20242211      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;
    20252250    }
    20262251  }
     
    20512276  //
    20522277  if (CpuMpData->CpuCount > 1) {
    2053     if (OldCpuMpData != NULL) {
     2278    if (MpHandOff != NULL) {
    20542279      //
    20552280      // Only needs to use this flag for DXE phase to update the wake up
     
    20682293    }
    20692294
    2070     if (OldCpuMpData != NULL) {
     2295    if (MpHandOff != NULL) {
    20712296      CpuMpData->InitFlag = ApInitDone;
    20722297    }
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/MpLib.h

    r99404 r101291  
    22  Common header file for MP Initialize Library.
    33
    4   Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
    55  Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
    66
     
    2828#include <Library/LocalApicLib.h>
    2929#include <Library/CpuLib.h>
    30 #include <Library/UefiCpuLib.h>
    3130#include <Library/TimerLib.h>
    3231#include <Library/SynchronizationLib.h>
     
    4140
    4241#include <Guid/MicrocodePatchHob.h>
     42#include "MpHandOff.h"
    4343
    4444#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')
    4553
    4654#define CPU_INIT_MP_LIB_HOB_GUID \
     
    178186  UINTN    ModeEntryOffset;
    179187  UINTN    RendezvousFunnelSize;
    180   UINT8    *RelocateApLoopFuncAddress;
    181   UINTN    RelocateApLoopFuncSize;
     188  UINT8    *RelocateApLoopFuncAddressGeneric;
     189  UINTN    RelocateApLoopFuncSizeGeneric;
     190  UINT8    *RelocateApLoopFuncAddressAmdSev;
     191  UINTN    RelocateApLoopFuncSizeAmdSev;
    182192  UINTN    ModeTransitionOffset;
    183193  UINTN    SwitchToRealNoNxOffset;
     
    312322#define AP_SAFE_STACK_SIZE   128
    313323#define AP_RESET_STACK_SIZE  AP_SAFE_STACK_SIZE
     324STATIC_ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0, "AP_SAFE_STACK_SIZE is not aligned with CPU_STACK_ALIGNMENT");
    314325
    315326#pragma pack(1)
     
    363374typedef
    364375  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**/
     397typedef
     398  VOID
     399(EFIAPI *ASM_RELOCATE_AP_LOOP_AMDSEV)(
    366400  IN BOOLEAN                 MwaitSupport,
    367401  IN UINTN                   ApTargetCState,
     
    402436  );
    403437
     438typedef 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
    404444/**
    405445  Get the pointer to CPU MP Data structure.
     
    436476
    437477/**
     478  Switch Context for each AP.
     479
     480**/
     481VOID
     482SwitchApContext (
     483  IN MP_HAND_OFF  *MpHandOff
     484  );
     485
     486/**
    438487  Get available EfiBootServicesCode memory below 4GB by specified size.
    439488
     
    463512GetSevEsAPMemory (
    464513  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**/
     522UINTN
     523CreatePageTable (
     524  IN UINTN  Address,
     525  IN UINTN  Length
    465526  );
    466527
     
    849910  );
    850911
     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**/
     917VOID
     918AmdSevUpdateCpuMpData (
     919  IN CPU_MP_DATA  *CpuMpData
     920  );
     921
    851922#endif
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf

    r99404 r101291  
    3737  MpLib.h
    3838  Microcode.c
    39 
     39  MpHandOff.h
    4040[Packages]
    4141  MdePkg/MdePkg.dec
     
    5050  MtrrLib
    5151  CpuLib
    52   UefiCpuLib
    5352  SynchronizationLib
    5453  PeiServicesLib
     
    6867  gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase                   ## SOMETIMES_CONSUMES
    6968  gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures              ## CONSUMES
     69  gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi             ## CONSUMES
    7070  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase                       ## CONSUMES
    7171  gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr       ## CONSUMES
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c

    r99404 r101291  
    127127  )
    128128{
    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  }
    130160
    131161  //
     
    759789    DEBUG_INFO,
    760790    "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
    761     __FUNCTION__,
     791    __func__,
    762792    CpuMpData->MicrocodePatchAddress,
    763793    CpuMpData->MicrocodePatchRegionSize
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c

    r99404 r101291  
    1313#include <Register/Amd/Fam17Msr.h>
    1414#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**/
     28STATIC
     29BOOLEAN
     30SevSnpPerformApAction (
     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}
    15111
    16112/**
     
    28124  )
    29125{
    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    }
    51171  }
    52172
     
    133253  SaveArea->SevFeatures = AsmReadMsr64 (MSR_SEV_STATUS) >> 2;
    134254
    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);
    192256}
    193257
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm

    r99404 r101291  
    347347
    348348SwitchToRealProcEnd:
     349
     350;-------------------------------------------------------------------------------------
     351;  AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
     352;-------------------------------------------------------------------------------------
     353
     354AsmRelocateApLoopAmdSevStart:
     355BITS 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
     402NoSevEsAmdSev:
     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    ;
     438o64 retf
     439
     440BITS 32
     441PmEntryAmdSev:
     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
     459MwaitCheckAmdSev:
     460    cmp        cl, 1              ; Check mwait-monitor support
     461    jnz        HltLoopAmdSev
     462    mov        ebx, edx           ; Save C-State to ebx
     463MwaitLoopAmdSev:
     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
     474HltLoopAmdSev:
     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    ;
     489BITS 64
     490    rep        vmmcall
     491BITS 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
     512DoHltAmdSev:
     513    cli
     514    hlt
     515    jmp        DoHltAmdSev
     516
     517BITS 64
     518AsmRelocateApLoopAmdSevEnd:
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm

    r99404 r101291  
    11;------------------------------------------------------------------------------ ;
    2 ; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
     2; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    33; SPDX-License-Identifier: BSD-2-Clause-Patent
    44;
     
    260260
    261261    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)]
    264263
    265264    mov        edi, esi
     
    280279
    281280;-------------------------------------------------------------------------------------
    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
     299AsmRelocateApLoopGenericStart:
     300    mov        rax, r9           ; CountTofinish
    335301    lock dec   dword [rax]       ; (*CountTofinish)--
    336302
    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
     309MwaitCheckGeneric:
    390310    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
     314MwaitLoopGeneric:
    394315    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
    396318    xor        ecx, ecx           ; ecx = 0
    397319    xor        edx, edx           ; edx = 0
    398320    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]
    400322    shl        eax, 4
    401323    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
     326HltLoopGeneric:
    443327    cli
    444328    hlt
    445     jmp        DoHlt
    446 
    447 BITS 64
    448 AsmRelocateApLoopEnd:
     329    jmp        HltLoopGeneric
     330
     331AsmRelocateApLoopGenericEnd:
    449332
    450333;-------------------------------------------------------------------------------------
     
    457340    mov        qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart
    458341    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
     342lea        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
    462348    mov        qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
    463349    mov        qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/MtrrLib.c

    r99404 r101291  
    757757  )
    758758{
    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;
    761764
    762765  AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL);
     
    766769  } else {
    767770    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    }
    768788  }
    769789
     
    12521272
    12531273  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 BOOLEAN
    1263 MtrrLibIsPowerOfTwo (
    1264   IN     UINT64  Operand
    1265   )
    1266 {
    1267   ASSERT (Operand != 0);
    1268   return (BOOLEAN)((Operand & (Operand - 1)) == 0);
    12691274}
    12701275
     
    16391644        }
    16401645
    1641         if ((Weight[M (Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo (Length)) {
     1646        if ((Weight[M (Start, Stop)] == MAX_WEIGHT) && IS_POW2 (Length)) {
    16421647          if (MtrrLibGetNumberOfTypes (
    16431648                Ranges,
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c

    r99404 r101291  
    22  Unit tests of the MtrrLib instance of the MtrrLib class
    33
    4   Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2020 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    3131  { 48, TRUE, TRUE, CacheWriteProtected, 12 },
    3232  { 48, TRUE, TRUE, CacheWriteCombining, 12 },
     33
     34  { 48, TRUE, TRUE, CacheWriteBack,      12, 7}, // 7 bits for MKTME
    3335};
    3436
     
    220222    );
    221223  GenerateValidAndConfigurableMtrrPairs (
    222     SystemParameter->PhysicalAddressBits,
     224    SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    223225    RawMtrrRange,
    224226    UcCount,
     
    233235  GetEffectiveMemoryRanges (
    234236    SystemParameter->DefaultCacheType,
    235     SystemParameter->PhysicalAddressBits,
     237    SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    236238    RawMtrrRange,
    237239    ExpectedVariableMtrrUsage,
     
    279281    CollectTestResult (
    280282      SystemParameter->DefaultCacheType,
    281       SystemParameter->PhysicalAddressBits,
     283      SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    282284      SystemParameter->VariableMtrrCount,
    283285      &LocalMtrrs,
     
    326328
    327329  RangeCount = Random32 (1, ARRAY_SIZE (Ranges));
    328   MaxAddress = 1ull << SystemParameter->PhysicalAddressBits;
     330  MaxAddress = 1ull << (SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits);
    329331
    330332  for (Index = 0; Index < RangeCount; Index++) {
     
    968970    );
    969971  GenerateValidAndConfigurableMtrrPairs (
    970     SystemParameter->PhysicalAddressBits,
     972    SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    971973    RawMtrrRange,
    972974    UcCount,
     
    981983  GetEffectiveMemoryRanges (
    982984    SystemParameter->DefaultCacheType,
    983     SystemParameter->PhysicalAddressBits,
     985    SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    984986    RawMtrrRange,
    985987    ExpectedVariableMtrrUsage,
     
    10201022    CollectTestResult (
    10211023      SystemParameter->DefaultCacheType,
    1022       SystemParameter->PhysicalAddressBits,
     1024      SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
    10231025      SystemParameter->VariableMtrrCount,
    10241026      &LocalMtrrs,
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h

    r99404 r101291  
    11/** @file
    22
    3   Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
     3  Copyright (c) 2020 - 2023, Intel Corporation. All rights reserved.<BR>
    44  SPDX-License-Identifier: BSD-2-Clause-Patent
    55
     
    4141  MTRR_MEMORY_CACHE_TYPE    DefaultCacheType;
    4242  UINT32                    VariableMtrrCount;
     43  UINT8                     MkTmeKeyidBits;
    4344} MTRR_LIB_SYSTEM_PARAMETER;
    4445
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c

    r99404 r101291  
    22  Unit tests of the MtrrLib instance of the MtrrLib class
    33
    4   Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2018 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1313};
    1414
    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;
     15UINT64                                       mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
     16MSR_IA32_MTRR_PHYSBASE_REGISTER              mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
     17MSR_IA32_MTRR_PHYSMASK_REGISTER              mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
     18MSR_IA32_MTRR_DEF_TYPE_REGISTER              mDefTypeMsr;
     19MSR_IA32_MTRRCAP_REGISTER                    mMtrrCapMsr;
     20MSR_IA32_TME_ACTIVATE_REGISTER               mTmeActivateMsr;
     21CPUID_VERSION_INFO_EDX                       mCpuidVersionInfoEdx;
     22CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX  mCpuidExtendedFeatureFlagsEcx;
     23CPUID_VIR_PHY_ADDRESS_SIZE_EAX               mCpuidVirPhyAddressSizeEax;
    2224
    2325BOOLEAN       mRandomInput;
     
    8890
    8991/**
     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**/
     123UINT32
     124EFIAPI
     125UnitTestMtrrLibAsmCpuidEx (
     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/**
    90180  Retrieves CPUID information.
    91181
     
    122212  )
    123213{
    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);
    153215}
    154216
     
    199261  if (MsrIndex == MSR_IA32_MTRRCAP) {
    200262    return mMtrrCapMsr.Uint64;
     263  }
     264
     265  if (MsrIndex == MSR_IA32_TME_ACTIVATE) {
     266    return mTmeActivateMsr.Uint64;
    201267  }
    202268
     
    318384  // Hook BaseLib functions used by MtrrLib that require some emulation.
    319385  //
    320   gUnitTestHostBaseLib.X86->AsmCpuid      = UnitTestMtrrLibAsmCpuid;
     386  gUnitTestHostBaseLib.X86->AsmCpuid   = UnitTestMtrrLibAsmCpuid;
     387  gUnitTestHostBaseLib.X86->AsmCpuidEx = UnitTestMtrrLibAsmCpuidEx;
     388
    321389  gUnitTestHostBaseLib.X86->AsmReadMsr64  = UnitTestMtrrLibAsmReadMsr64;
    322390  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  }
    323401
    324402  return UNIT_TEST_PASSED;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c

    r99404 r101291  
    22  CPU Features Initialize functions.
    33
    4   Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    6868  DisplayedFamily = Eax.Bits.FamilyId;
    6969  if (Eax.Bits.FamilyId == 0x0F) {
    70     DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);
     70    DisplayedFamily += Eax.Bits.ExtendedFamilyId;
    7171  }
    7272
    7373  DisplayedModel = Eax.Bits.Model;
    7474  if ((Eax.Bits.FamilyId == 0x06) || (Eax.Bits.FamilyId == 0x0f)) {
    75     DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);
     75    DisplayedModel += (Eax.Bits.ExtendedModelId << 4);
    7676  }
    7777
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h

    r99404 r101291  
    1010#define CPU_FEATURES_LIB_H_
    1111
     12#include <Guid/SmmBaseHob.h>
    1213#include <Library/SmmCpuFeaturesLib.h>
    1314#include <Library/BaseLib.h>
     
    1516#include <Library/MemoryAllocationLib.h>
    1617#include <Library/DebugLib.h>
     18#include <Library/HobLib.h>
    1719
    1820/**
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c

    r99404 r101291  
    22Implementation shared across all library instances.
    33
    4 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) Microsoft Corporation.<BR>
    66SPDX-License-Identifier: BSD-2-Clause-Patent
     
    4040
    4141//
     42// Indicate SmBase for each Processors has been relocated or not. If TRUE,
     43// means no need to do the relocation in SmmCpuFeaturesInitializeProcessor().
     44//
     45BOOLEAN  mSmmCpuFeaturesSmmRelocated;
     46
     47//
    4248// Set default value to assume MTRRs need to be configured on each SMI
    4349//
     
    145151  mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ());
    146152  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);
    147159}
    148160
     
    188200
    189201  //
    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  }
    194211
    195212  //
     
    401418  }
    402419}
     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**/
     452UINT64
     453EFIAPI
     454SmmCpuFeaturesHookReturnFromSmm (
     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**/
     477BOOLEAN
     478EFIAPI
     479SmmCpuFeaturesIsSmmRegisterSupported (
     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  
    22#  The CPU specific programming for PiSmmCpuDxeSmm module.
    33#
    4 #  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
     4#  Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55#  SPDX-License-Identifier: BSD-2-Clause-Patent
    66#
     
    3434  MemoryAllocationLib
    3535  DebugLib
     36  HobLib
     37
     38[Guids]
     39  gSmmBaseHobGuid                ## CONSUMES
    3640
    3741[Pcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c

    r99404 r101291  
    1717
    1818#include "CpuFeaturesLib.h"
    19 
    20 /**
    21   This function updates the SMRAM save state on the currently executing CPU
    22   to resume execution at a specific address after an RSM instruction.  This
    23   function must evaluate the SMRAM save state to determine the execution mode
    24   the RSM instruction resumes and update the resume execution address with
    25   either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart
    26   flag in the SMRAM save state must always be cleared.  This function returns
    27   the value of the instruction pointer from the SMRAM save state that was
    28   replaced.  If this function returns 0, then the SMRAM save state was not
    29   modified.
    30 
    31   This function is called during the very first SMI on each CPU after
    32   SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
    33   to signal that the SMBASE of each CPU has been updated before the default
    34   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 value
    37                                       must be between 0 and the NumberOfCpus
    38                                       field in the System Management System Table
    39                                       (SMST).
    40   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
    41                                       currently executing CPU.
    42   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
    43                                       32-bit execution mode from 64-bit SMM.
    44   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
    45                                       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 state
    49                before it was replaced.
    50 **/
    51 UINT64
    52 EFIAPI
    53 SmmCpuFeaturesHookReturnFromSmm (
    54   IN UINTN                 CpuIndex,
    55   IN SMRAM_SAVE_STATE_MAP  *CpuState,
    56   IN UINT64                NewInstructionPointer32,
    57   IN UINT64                NewInstructionPointer
    58   )
    59 {
    60   return 0;
    61 }
    6219
    6320/**
     
    9249
    9350/**
    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 field
    98                        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 CPU
    102                  specified by CpuIndex.
    103   @retval FALSE  The SMM register specified by RegName is not supported by the
    104                  CPU specified by CpuIndex.
    105 **/
    106 BOOLEAN
    107 EFIAPI
    108 SmmCpuFeaturesIsSmmRegisterSupported (
    109   IN UINTN         CpuIndex,
    110   IN SMM_REG_NAME  RegName
    111   )
    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 function
    122   returns EFI_UNSUPPORTED, then the caller is responsible for reading the
    123   SMM Save Sate register.
    124 
    125   @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
    126                         value must be between 0 and the NumberOfCpus field in
    127                         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 read
    131                         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_STATUS
    139 EFIAPI
    140 SmmCpuFeaturesReadSaveStateRegister (
    141   IN  UINTN                        CpuIndex,
    142   IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
    143   IN  UINTN                        Width,
    144   OUT VOID                         *Buffer
    145   )
    146 {
    147   return EFI_UNSUPPORTED;
    148 }
    149 
    150 /**
    151   Writes an SMM Save State register on the target processor.  If this function
    152   returns EFI_UNSUPPORTED, then the caller is responsible for writing the
    153   SMM Save Sate register.
    154 
    155   @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
    156                        value must be between 0 and the NumberOfCpus field in
    157                        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_STATUS
    167 EFIAPI
    168 SmmCpuFeaturesWriteSaveStateRegister (
    169   IN UINTN                        CpuIndex,
    170   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    171   IN UINTN                        Width,
    172   IN CONST VOID                   *Buffer
    173   )
    174 {
    175   return EFI_UNSUPPORTED;
    176 }
    177 
    178 /**
    17951  This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
    18052  notification is completely processed.
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf

    r99404 r101291  
    33#  is included.
    44#
    5 #  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
     5#  Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    66#  SPDX-License-Identifier: BSD-2-Clause-Patent
    77#
     
    6565  gEfiAcpi20TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable
    6666  gEfiAcpi10TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable
     67  gSmmBaseHobGuid                          ## CONSUMES
    6768
    6869[Pcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c

    r99404 r101291  
    22  SMM STM support functions
    33
    4   Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
     4  Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    55  SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    99#include <PiMm.h>
    1010#include <Library/BaseMemoryLib.h>
    11 #include <Library/HobLib.h>
    1211#include <Library/UefiBootServicesTableLib.h>
    1312#include <Library/SmmServicesTableLib.h>
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf

    r99404 r101291  
    22#  Standalone MM CPU specific programming.
    33#
    4 #  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
     4#  Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55#  Copyright (c) Microsoft Corporation.<BR>
    66#  SPDX-License-Identifier: BSD-2-Clause-Patent
     
    3535  MemoryAllocationLib
    3636  PcdLib
     37  HobLib
     38
     39[Guids]
     40  gSmmBaseHobGuid                ## CONSUMES
    3741
    3842[FixedPcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c

    r99404 r101291  
    239239      );
    240240  } 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));
    242242  }
    243243
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c

    r99404 r101291  
    22Code for Processor S3 restoration
    33
    4 Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
    55SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    824824  }
    825825
    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  }
    830843
    831844  //
     
    920933      DEBUG_ERROR,
    921934      "ERROR:%a(): HOB(gEfiAcpiVariableGuid=%g) needed by S3 resume doesn't exist!\n",
    922       __FUNCTION__,
     935      __func__,
    923936      &gEfiAcpiVariableGuid
    924937      ));
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/CpuService.c

    r99404 r101291  
    22Implementation of SMM CPU Services Protocol.
    33
    4 Copyright (c) 2011 - 2022, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
    55SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    422422  }
    423423
    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  }
    429436
    430437ON_EXIT:
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c

    r99404 r101291  
    22Page table manipulation functions for IA-32 processors
    33
    4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
    66
     
    3232
    3333  mPhysicalAddressBits = 32;
     34  mPagingMode          = PagingPae;
    3435
    3536  if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||
     
    6364  }
    6465
    65   return Gen4GPageTable (TRUE);
     66  return GenSmmPageTable (PagingPae, mPhysicalAddressBits);
    6667}
    6768
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c

    r99404 r101291  
    22  SMM CPU misc functions for Ia32 arch specific.
    33
    4 Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    55SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1515
    1616extern BOOLEAN  mCetSupported;
    17 extern UINTN    mSmmShadowStackSize;
    1817
    1918X86_ASSEMBLY_PATCH_LABEL  mPatchCetPl0Ssp;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c

    r99404 r101291  
    1919  )
    2020{
    21   mSmmS3ResumeState->SmmS3Cr3 = Gen4GPageTable (TRUE);
     21  mSmmS3ResumeState->SmmS3Cr3 = GenSmmPageTable (PagingPae, mPhysicalAddressBits);
    2222
    2323  return;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c

    r99404 r101291  
    22SMM MP service implementation
    33
    4 Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
    66
     
    3030UINT32  *mPackageFirstThreadIndex = NULL;
    3131
    32 extern UINTN  mSmmShadowStackSize;
    33 
    3432/**
    3533  Performs an atomic compare exchange operation to get semaphore.
     
    351349  UINT32   DelayedCount;
    352350  UINT32   BlockedCount;
     351
     352  PERF_FUNCTION_BEGIN ();
    353353
    354354  DelayedCount = 0;
     
    440440  }
    441441
    442   return;
     442  PERF_FUNCTION_END ();
    443443}
    444444
     
    578578  ApCount = 0;
    579579
     580  PERF_FUNCTION_BEGIN ();
     581
    580582  //
    581583  // Flag BSP's presence
     
    776778
    777779  //
     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  //
    778789  // Reset the tokens buffer.
    779790  //
     
    793804  *mSmmMpSyncData->AllCpusInSync            = FALSE;
    794805  mSmmMpSyncData->AllApArrivedWithException = FALSE;
     806
     807  PERF_FUNCTION_END ();
    795808}
    796809
     
    10001013  //
    10011014  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 PAE
    1008   @return         PageTable Address
    1009 
    1010 **/
    1011 UINT32
    1012 Gen4GPageTable (
    1013   IN      BOOLEAN  Is32BitPageTable
    1014   )
    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 table
    1046   //
    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 first
    1055   //
    1056   ZeroMem (Pte, EFI_PAGES_TO_SIZE (1));
    1057 
    1058   //
    1059   // Set Page Directory Pointers
    1060   //
    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 Entries
    1070   //
    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 Entries
    1084       //
    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-present
    1091           //
    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 0
    1114     } else {
    1115       // Create 4K-page entries
    1116       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 left
    1124       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;
    11321015}
    11331016
     
    17241607  ASSERT (CpuIndex < mMaxNumberOfCpus);
    17251608
     1609  if (mSmmRelocated) {
     1610    ASSERT (mSmmInitialized != NULL);
     1611  }
     1612
    17261613  //
    17271614  // Save Cr2 because Page Fault exception in SMM may override its value,
     
    17311618  SaveCr2 (&Cr2);
    17321619
     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
    17331639  //
    17341640  // Call the user register Startup function first.
     
    17411647  // Perform CPU specific entry hooks
    17421648  //
     1649  PERF_CODE (
     1650    MpPerfBegin (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousEntry));
     1651    );
    17431652  SmmCpuFeaturesRendezvousEntry (CpuIndex);
     1653  PERF_CODE (
     1654    MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousEntry));
     1655    );
    17441656
    17451657  //
    17461658  // Determine if this is a valid SMI
    17471659  //
     1660  PERF_CODE (
     1661    MpPerfBegin (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (PlatformValidSmi));
     1662    );
    17481663  ValidSmi = PlatformValidSmi ();
     1664  PERF_CODE (
     1665    MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (PlatformValidSmi));
     1666    );
    17491667
    17501668  //
     
    18761794
    18771795Exit:
     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    );
    18781806  SmmCpuFeaturesRendezvousExit (CpuIndex);
     1807  PERF_CODE (
     1808    MpPerfEnd (CpuIndex, SMM_MP_PERF_PROCEDURE_ID (SmmRendezvousExit));
     1809    );
    18791810
    18801811  //
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c

    r99404 r101291  
    22Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
    33
    4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
     6Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
    67
    78SPDX-License-Identifier: BSD-2-Clause-Patent
     
    6061//
    6162volatile BOOLEAN  *mRebased;
    62 volatile BOOLEAN  mIsBsp;
    6363
    6464///
     
    8585
    8686EFI_CPU_INTERRUPT_HANDLER  mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
     87
     88BOOLEAN           mSmmRelocated    = FALSE;
     89volatile BOOLEAN  *mSmmInitialized = NULL;
     90UINT32            mBspApicId       = 0;
    8791
    8892//
     
    274278  }
    275279
    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);
    280281
    281282  return Status;
     
    326327  }
    327328
    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);
    332330
    333331  return Status;
     
    344342  )
    345343{
    346   UINT32  ApicId;
    347   UINTN   Index;
     344  UINT32   ApicId;
     345  UINTN    Index;
     346  BOOLEAN  IsBsp;
    348347
    349348  //
     
    353352  ApicId = GetApicId ();
    354353
     354  IsBsp = (BOOLEAN)(mBspApicId == ApicId);
     355
    355356  ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);
    356357
    357358  for (Index = 0; Index < mNumberOfCpus; Index++) {
    358359    if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
     360      PERF_CODE (
     361        MpPerfBegin (Index, SMM_MP_PERF_PROCEDURE_ID (SmmInitHandler));
     362        );
    359363      //
    360364      // Initialize SMM specific features on the currently executing CPU
     
    362366      SmmCpuFeaturesInitializeProcessor (
    363367        Index,
    364         mIsBsp,
     368        IsBsp,
    365369        gSmmCpuPrivate->ProcessorInfo,
    366370        &mCpuHotPlugData
     
    372376        //
    373377        CheckFeatureSupported ();
    374       }
    375 
    376       if (mIsBsp) {
     378      } else if (IsBsp) {
    377379        //
    378380        // BSP rebase is already done above.
     
    382384      }
    383385
    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        );
    388396
    389397      return;
     
    392400
    393401  ASSERT (FALSE);
     402}
     403
     404/**
     405  Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
     406
     407**/
     408VOID
     409ExecuteFirstSmiInit (
     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 ();
    394452}
    395453
     
    410468  SMRAM_SAVE_STATE_MAP  *CpuStatePtr;
    411469  UINT8                 *U8Ptr;
    412   UINT32                ApicId;
    413470  UINTN                 Index;
    414471  UINTN                 BspIndex;
     472
     473  PERF_FUNCTION_BEGIN ();
    415474
    416475  //
     
    451510  // Retrieve the local APIC ID of current processor
    452511  //
    453   ApicId = GetApicId ();
     512  mBspApicId = GetApicId ();
    454513
    455514  //
     
    457516  // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate
    458517  //
    459   mIsBsp   = FALSE;
    460518  BspIndex = (UINTN)-1;
    461519  for (Index = 0; Index < mNumberOfCpus; Index++) {
    462520    mRebased[Index] = FALSE;
    463     if (ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
     521    if (mBspApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
    464522      SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);
    465523      //
     
    480538  //
    481539  ASSERT (BspIndex != (UINTN)-1);
    482   mIsBsp = TRUE;
    483   SendSmiIpi (ApicId);
     540  SendSmiIpi (mBspApicId);
    484541  //
    485542  // Wait for the BSP to finish its 1st SMI
     
    493550  CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2));
    494551  CopyMem (U8Ptr, BakBuf, sizeof (BakBuf));
     552  PERF_FUNCTION_END ();
    495553}
    496554
     
    564622  UINTN                     ModelId;
    565623  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 ();
    566631
    567632  //
     
    636701
    637702  gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus = mMaxNumberOfCpus;
     703
     704  PERF_CODE (
     705    InitializeMpPerf (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);
     706    );
    638707
    639708  //
     
    792861
    793862  //
    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;
    808884  } 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  }
    814907
    815908  //
     
    846939  //
    847940  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
    849943    gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP);
    850944    gSmmCpuPrivate->CpuSaveState[Index]     = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET);
     
    852946
    853947    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]);
    855949      ASSERT_EFI_ERROR (Status);
    856950      mCpuHotPlugData.ApicId[Index] = gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId;
     
    9591053
    9601054  //
    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  }
    9721072
    9731073  DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));
     
    9911091        );
    9921092      if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
    993         SetNotPresentPage (
     1093        ConvertMemoryPageAttributes (
    9941094          Cr3,
     1095          mPagingMode,
    9951096          (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
    9971101          );
    9981102      }
    9991103    }
     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 ();
    10001119  }
    10011120
     
    10961215  DEBUG ((DEBUG_INFO, "SMM CPU Module exit from SMRAM with EFI_SUCCESS\n"));
    10971216
     1217  PERF_FUNCTION_END ();
    10981218  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**/
     1231INTN
     1232EFIAPI
     1233CpuSmramRangeCompare (
     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;
    10991245}
    11001246
     
    11201266  UINT64                    MaxSize;
    11211267  BOOLEAN                   Found;
     1268  EFI_SMRAM_DESCRIPTOR      SmramDescriptor;
    11221269
    11231270  //
     
    11411288
    11421289  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);
    11431295
    11441296  //
     
    12501402  EFI_STATUS  Status;
    12511403
     1404  PERF_FUNCTION_BEGIN ();
     1405
    12521406  //
    12531407  // Check to see if the Feature Control MSR is supported on this CPU
     
    12561410  if (!SmmCpuFeaturesIsSmmRegisterSupported (Index, SmmRegFeatureControl)) {
    12571411    mSmmCodeAccessCheckEnable = FALSE;
     1412    PERF_FUNCTION_END ();
    12581413    return;
    12591414  }
     
    12651420  if ((AsmReadMsr64 (EFI_MSR_SMM_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) == 0) {
    12661421    mSmmCodeAccessCheckEnable = FALSE;
     1422    PERF_FUNCTION_END ();
    12671423    return;
    12681424  }
     
    13211477    }
    13221478  }
     1479
     1480  PERF_FUNCTION_END ();
    13231481}
    13241482
     
    14421600{
    14431601  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
    14441617    //
    14451618    // Start SMM Profile feature
     
    14761649    ConfigSmmCodeAccessCheck ();
    14771650
     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);
    14781656    SmmCpuFeaturesCompleteSmmReadyToLock ();
     1657    PERF_END (NULL, "SmmCompleteReadyToLock", NULL, 0);
    14791658
    14801659    //
     
    14821661    //
    14831662    mSmmReadyToLock = FALSE;
     1663
     1664    PERF_FUNCTION_END ();
    14841665  }
    14851666}
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h

    r99404 r101291  
    22Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
    33
    4 Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
     6Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
    67
    78SPDX-License-Identifier: BSD-2-Clause-Patent
     
    2627#include <Guid/MemoryAttributesTable.h>
    2728#include <Guid/PiSmmMemoryAttributesTable.h>
     29#include <Guid/SmmBaseHob.h>
    2830
    2931#include <Library/BaseLib.h>
     
    4547#include <Library/LocalApicLib.h>
    4648#include <Library/CpuLib.h>
    47 #include <Library/UefiCpuLib.h>
    4849#include <Library/CpuExceptionHandlerLib.h>
    4950#include <Library/ReportStatusCodeLib.h>
     
    5152#include <Library/PeCoffGetEntryPointLib.h>
    5253#include <Library/RegisterCpuFeaturesLib.h>
     54#include <Library/PerformanceLib.h>
     55#include <Library/CpuPageTableLib.h>
     56#include <Library/MmSaveStateLib.h>
    5357
    5458#include <AcpiCpuData.h>
     
    6064#include "CpuService.h"
    6165#include "SmmProfile.h"
     66#include "SmmMpPerf.h"
    6267
    6368//
     
    261266extern EFI_MM_MP_PROTOCOL    mSmmMp;
    262267extern BOOLEAN               m5LevelPagingNeeded;
     268extern PAGING_MODE           mPagingMode;
     269extern UINTN                 mSmmShadowStackSize;
    263270
    264271///
     
    350357
    351358/**
    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**/
     362VOID
     363EFIAPI
     364SmmInitHandler (
     365  VOID
     366  );
     367
     368/**
     369  Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
     370
     371**/
     372VOID
     373ExecuteFirstSmiInit (
     374  VOID
     375  );
     376
     377extern BOOLEAN            mSmmRelocated;
     378extern volatile  BOOLEAN  *mSmmInitialized;
     379extern UINT32             mBspApicId;
    404380
    405381extern CONST UINT8        gcSmmInitTemplate[];
     
    529505
    530506/**
     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**/
     515UINTN
     516GenSmmPageTable (
     517  IN PAGING_MODE  PagingMode,
     518  IN UINT8        PhysicalAddressBits
     519  );
     520
     521/**
    531522  Initialize global data for MP synchronization.
    532523
     
    683674  IN      UINTN             CpuIndex,
    684675  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**/
     704RETURN_STATUS
     705ConvertMemoryPageAttributes (
     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
    685713  );
    686714
     
    9861014
    9871015  @param[in]   PageTableBase    The page table base.
    988   @param[in]   EnablePML5Paging If PML5 paging is enabled.
     1016  @param[in]   PagingMode       The paging mode.
    9891017  @param[in]   BaseAddress      The physical address that is the start address of a memory region.
    9901018  @param[in]   Length           The size in bytes of the memory region.
    9911019  @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.
    9931020
    9941021  @retval EFI_SUCCESS           The attributes were set for the memory region.
     
    10081035EFI_STATUS
    10091036SmmSetMemoryAttributesEx (
    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
    10161042  );
    10171043
     
    10211047
    10221048  @param[in]   PageTableBase    The page table base.
    1023   @param[in]   EnablePML5Paging If PML5 paging is enabled.
     1049  @param[in]   PagingMode       The paging mode.
    10241050  @param[in]   BaseAddress      The physical address that is the start address of a memory region.
    10251051  @param[in]   Length           The size in bytes of the memory region.
    10261052  @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.
    10281053
    10291054  @retval EFI_SUCCESS           The attributes were cleared for the memory region.
     
    10321057  @retval EFI_INVALID_PARAMETER Length is zero.
    10331058                                Attributes specified an illegal combination of attributes that
    1034                                 cannot be set together.
     1059                                cannot be cleared together.
    10351060  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
    10361061                                the memory resource range.
    10371062  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
    10381063                                resource range specified by BaseAddress and Length.
    1039                                 The bit mask of attributes is not support for the memory resource
     1064                                The bit mask of attributes is not supported for the memory resource
    10401065                                range specified by BaseAddress and Length.
    10411066
     
    10441069SmmClearMemoryAttributesEx (
    10451070  IN  UINTN                 PageTableBase,
    1046   IN  BOOLEAN               EnablePML5Paging,
     1071  IN  PAGING_MODE           PagingMode,
    10471072  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
    10481073  IN  UINT64                Length,
    1049   IN  UINT64                Attributes,
    1050   OUT BOOLEAN               *IsSplitted  OPTIONAL
     1074  IN  UINT64                Attributes
    10511075  );
    10521076
     
    11691193EFI_STATUS
    11701194SetShadowStack (
    1171   IN  UINTN                 Cr3,
    1172   IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
    1173   IN  UINT64                Length
    1174   );
    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_STATUS
    1186 SetNotPresentPage (
    11871195  IN  UINTN                 Cr3,
    11881196  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
     
    15451553  );
    15461554
     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**/
     1561VOID
     1562DisableReadOnlyPageWriteProtect (
     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**/
     1573VOID
     1574EnableReadOnlyPageWriteProtect (
     1575  BOOLEAN  WpEnabled,
     1576  BOOLEAN  CetEnabled
     1577  );
     1578
    15471579#endif
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf

    r99404 r101291  
    55# provides CPU specific services in SMM.
    66#
    7 # Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
     7# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    88# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
     9# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
    910#
    1011# SPDX-License-Identifier: BSD-2-Clause-Patent
     
    4344  SmmMp.h
    4445  SmmMp.c
     46  SmmMpPerf.h
     47  SmmMpPerf.c
    4548
    4649[Sources.Ia32]
     
    9093  PciLib
    9194  LocalApicLib
    92   UefiCpuLib
    9395  SmmCpuPlatformHookLib
    9496  CpuExceptionHandlerLib
     
    99101  SmmCpuFeaturesLib
    100102  PeCoffGetEntryPointLib
     103  PerformanceLib
     104  CpuPageTableLib
     105  MmSaveStateLib
    101106
    102107[Protocols]
     
    115120  gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
    116121  gEfiMemoryAttributesTableGuid            ## CONSUMES ## SystemTable
     122  gSmmBaseHobGuid                          ## CONSUMES
    117123
    118124[FeaturePcd]
     
    126132  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
    127133  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode         ## CONSUMES
     134  gUefiCpuPkgTokenSpaceGuid.PcdSmmApPerfLogEnable                  ## CONSUMES
    128135
    129136[Pcd]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c

    r99404 r101291  
    11/** @file
    22
    3 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
     3Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
    44SPDX-License-Identifier: BSD-2-Clause-Patent
    55
     
    2727EFI_MEMORY_ATTRIBUTES_TABLE  *mUefiMemoryAttributesTable = NULL;
    2828
    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;
     29BOOLEAN      mIsShadowStack      = FALSE;
     30BOOLEAN      m5LevelPagingNeeded = FALSE;
     31PAGING_MODE  mPagingMode         = PagingModeMax;
    3732
    3833//
     
    4742
    4843/**
     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**/
     49VOID
     50DisableReadOnlyPageWriteProtect (
     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**/
     79VOID
     80EnableReadOnlyPageWriteProtect (
     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/**
    49102  Initialize a buffer pool for page table use only.
    50103
     
    68121  )
    69122{
    70   VOID      *Buffer;
    71   BOOLEAN   CetEnabled;
    72   BOOLEAN   WpEnabled;
    73   IA32_CR0  Cr0;
     123  VOID     *Buffer;
     124  BOOLEAN  WpEnabled;
     125  BOOLEAN  CetEnabled;
    74126
    75127  //
     
    108160  //
    109161  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);
    125163    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);
    138165  }
    139166
     
    184211
    185212  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 UINTN
    196 PageAttributeToLength (
    197   IN PAGE_ATTRIBUTE  PageAttribute
    198   )
    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 UINTN
    219 PageAttributeToMask (
    220   IN PAGE_ATTRIBUTE  PageAttribute
    221   )
    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;
    232213}
    233214
     
    355336
    356337/**
    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 VOID
    365 ConvertPageEntryAttribute (
    366   IN  UINT64   *PageEntry,
    367   IN  UINT64   Attributes,
    368   IN  BOOLEAN  IsSet,
    369   OUT BOOLEAN  *IsModified
    370   )
    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 setup
    390         // ReadOnly page need set Dirty bit for shadow stack
    391         NewPageEntry |= IA32_PG_D;
    392         // Clear user bit for supervisor shadow stack
    393         NewPageEntry &= ~(UINT64)IA32_PG_U;
    394       } else {
    395         // Runtime update
    396         // 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_ATTRIBUTE
    435 NeedSplitPage (
    436   IN  PHYSICAL_ADDRESS  BaseAddress,
    437   IN  UINT64            Length,
    438   IN  UINT64            *PageEntry,
    439   IN  PAGE_ATTRIBUTE    PageAttribute
    440   )
    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_STATUS
    469 SplitPage (
    470   IN  UINT64          *PageEntry,
    471   IN  PAGE_ATTRIBUTE  PageAttribute,
    472   IN  PAGE_ATTRIBUTE  SplitAttribute
    473   )
    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 4K
    484     //
    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 2M
    506     // 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 /**
    532338  This function modifies the page attributes for the memory region specified by BaseAddress and
    533339  Length from their current attributes to the attributes specified by Attributes.
     
    536342
    537343  @param[in]   PageTableBase    The page table base.
    538   @param[in]   EnablePML5Paging If PML5 paging is enabled.
     344  @param[in]   PagingMode       The paging mode.
    539345  @param[in]   BaseAddress      The physical address that is the start address of a memory region.
    540346  @param[in]   Length           The size in bytes of the memory region.
    541347  @param[in]   Attributes       The bit mask of attributes to modify for the memory region.
    542348  @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.
    544349  @param[out]  IsModified       TRUE means page table modified. FALSE means page table not modified.
    545350
     
    560365ConvertMemoryPageAttributes (
    561366  IN  UINTN             PageTableBase,
    562   IN  BOOLEAN           EnablePML5Paging,
     367  IN  PAGING_MODE       PagingMode,
    563368  IN  PHYSICAL_ADDRESS  BaseAddress,
    564369  IN  UINT64            Length,
    565370  IN  UINT64            Attributes,
    566371  IN  BOOLEAN           IsSet,
    567   OUT BOOLEAN           *IsSplitted   OPTIONAL,
    568372  OUT BOOLEAN           *IsModified   OPTIONAL
    569373  )
    570374{
    571   UINT64                *PageEntry;
    572   PAGE_ATTRIBUTE        PageAttribute;
    573   UINTN                 PageEntryLength;
    574   PAGE_ATTRIBUTE        SplitAttribute;
    575375  RETURN_STATUS         Status;
    576   BOOLEAN               IsEntryModified;
     376  IA32_MAP_ATTRIBUTE    PagingAttribute;
     377  IA32_MAP_ATTRIBUTE    PagingAttrMask;
     378  UINTN                 PageTableBufferSize;
     379  VOID                  *PageTableBuffer;
    577380  EFI_PHYSICAL_ADDRESS  MaximumSupportMemAddress;
     381  IA32_MAP_ENTRY        *Map;
     382  UINTN                 Count;
     383  UINTN                 Index;
     384  UINT64                OverlappedRangeBase;
     385  UINT64                OverlappedRangeLimit;
    578386
    579387  ASSERT (Attributes != 0);
     
    582390  ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0);
    583391  ASSERT ((Length & (SIZE_4KB - 1)) == 0);
     392  ASSERT (PageTableBase != 0);
    584393
    585394  if (Length == 0) {
     
    600409  }
    601410
    602   //  DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
    603 
    604   if (IsSplitted != NULL) {
    605     *IsSplitted = FALSE;
    606   }
    607 
    608411  if (IsModified != NULL) {
    609412    *IsModified = FALSE;
    610413  }
    611414
    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);
    628487        }
     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);
    629510      }
    630511
    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);
    656539
    657540  return RETURN_SUCCESS;
     
    698581
    699582  @param[in]   PageTableBase    The page table base.
    700   @param[in]   EnablePML5Paging If PML5 paging is enabled.
     583  @param[in]   PagingMode       The paging mode.
    701584  @param[in]   BaseAddress      The physical address that is the start address of a memory region.
    702585  @param[in]   Length           The size in bytes of the memory region.
    703586  @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.
    705587
    706588  @retval EFI_SUCCESS           The attributes were set for the memory region.
     
    721603SmmSetMemoryAttributesEx (
    722604  IN  UINTN                 PageTableBase,
    723   IN  BOOLEAN               EnablePML5Paging,
     605  IN  PAGING_MODE           PagingMode,
    724606  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
    725607  IN  UINT64                Length,
    726   IN  UINT64                Attributes,
    727   OUT BOOLEAN               *IsSplitted  OPTIONAL
     608  IN  UINT64                Attributes
    728609  )
    729610{
     
    731612  BOOLEAN     IsModified;
    732613
    733   Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified);
     614  Status = ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseAddress, Length, Attributes, TRUE, &IsModified);
    734615  if (!EFI_ERROR (Status)) {
    735616    if (IsModified) {
     
    749630
    750631  @param[in]   PageTableBase    The page table base.
    751   @param[in]   EnablePML5Paging If PML5 paging is enabled.
     632  @param[in]   PagingMode       The paging mode.
    752633  @param[in]   BaseAddress      The physical address that is the start address of a memory region.
    753634  @param[in]   Length           The size in bytes of the memory region.
    754635  @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.
    756636
    757637  @retval EFI_SUCCESS           The attributes were cleared for the memory region.
     
    772652SmmClearMemoryAttributesEx (
    773653  IN  UINTN                 PageTableBase,
    774   IN  BOOLEAN               EnablePML5Paging,
     654  IN  PAGING_MODE           PagingMode,
    775655  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
    776656  IN  UINT64                Length,
    777   IN  UINT64                Attributes,
    778   OUT BOOLEAN               *IsSplitted  OPTIONAL
     657  IN  UINT64                Attributes
    779658  )
    780659{
     
    782661  BOOLEAN     IsModified;
    783662
    784   Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified);
     663  Status = ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseAddress, Length, Attributes, FALSE, &IsModified);
    785664  if (!EFI_ERROR (Status)) {
    786665    if (IsModified) {
     
    824703  )
    825704{
    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);
    834709}
    835710
     
    863738  )
    864739{
    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);
    873744}
    874745
     
    892763
    893764  mIsShadowStack = TRUE;
    894   Status         = SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RO, NULL);
     765  Status         = SmmSetMemoryAttributesEx (Cr3, mPagingMode, BaseAddress, Length, EFI_MEMORY_RO);
    895766  mIsShadowStack = FALSE;
    896767
    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_STATUS
    910 SetNotPresentPage (
    911   IN  UINTN                 Cr3,
    912   IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
    913   IN  UINT64                Length
    914   )
    915 {
    916   EFI_STATUS  Status;
    917 
    918   Status = SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RP, NULL);
    919768  return Status;
    920769}
     
    1081930
    1082931/**
     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**/
     940VOID
     941SetMemMapWithNonPresentRange (
     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/**
    1083996  This function sets memory attribute according to MemoryAttributesTable.
    1084997**/
     
    10941007  UINTN                                 Index;
    10951008  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;
    10961016
    10971017  SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
     
    11001020    return;
    11011021  }
     1022
     1023  PERF_FUNCTION_BEGIN ();
    11021024
    11031025  DEBUG ((DEBUG_INFO, "MemoryAttributesTable:\n"));
     
    11201042  }
    11211043
     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
    11221062  MemoryMap = MemoryMapStart;
    11231063  for (Index = 0; Index < MemoryMapEntryCount; Index++) {
    11241064    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      );
    11481086
    11491087    MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
    11501088  }
     1089
     1090  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
     1091  FreePool (Map);
    11511092
    11521093  PatchSmmSaveStateMap ();
    11531094  PatchGdtIdtMap ();
    11541095
    1155   return;
     1096  PERF_FUNCTION_END ();
    11561097}
    11571098
     
    14541395  UINTN                  Index;
    14551396  EFI_MEMORY_DESCRIPTOR  *Entry;
     1397  BOOLEAN                WpEnabled;
     1398  BOOLEAN                CetEnabled;
     1399
     1400  PERF_FUNCTION_BEGIN ();
    14561401
    14571402  DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
     1403
     1404  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
    14581405
    14591406  if (mUefiMemoryMap != NULL) {
     
    15351482  }
    15361483
     1484  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
     1485
    15371486  //
    15381487  // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
    15391488  //
     1489
     1490  PERF_FUNCTION_END ();
    15401491}
    15411492
     
    16751626
    16761627/**
     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**/
     1636UINTN
     1637GenSmmPageTable (
     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/**
    16771693  This function retrieves the attributes of the memory region specified by
    16781694  BaseAddress and Length. If different attributes are got from different part
     
    18001816    // Set entire pool including header, used-memory and left free-memory as ReadOnly in SMM page table.
    18011817    //
    1802     ConvertMemoryPageAttributes (PageTableBase, m5LevelPagingNeeded, Address, PoolSize, EFI_MEMORY_RO, TRUE, NULL, NULL);
     1818    ConvertMemoryPageAttributes (PageTableBase, mPagingMode, Address, PoolSize, EFI_MEMORY_RO, TRUE, NULL);
    18031819    Pool = Pool->NextPool;
    18041820  } while (Pool != HeadPool);
     
    18571873  )
    18581874{
     1875  BOOLEAN  WpEnabled;
    18591876  BOOLEAN  CetEnabled;
    18601877
     
    18631880  }
    18641881
     1882  PERF_FUNCTION_BEGIN ();
    18651883  DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));
    18661884
     
    18691887  // We need *write* page table memory, to mark itself to be *read only*.
    18701888  //
    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);
    18801890
    18811891  // Set memory used by page table as Read Only.
     
    18861896  // Enable write protection, after page table attribute updated.
    18871897  //
    1888   AsmWriteCr0 (AsmReadCr0 () | CR0_WP);
     1898  EnableReadOnlyPageWriteProtect (TRUE, CetEnabled);
    18891899  mIsReadOnlyPageTable = TRUE;
    18901900
     
    18931903  //
    18941904  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  
    374374  //
    375375  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**/
     388INTN
     389EFIAPI
     390ProtectionRangeCompare (
     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;
    376402}
    377403
     
    398424  UINT64                           High4KBPageSize;
    399425  UINT64                           Low4KBPageSize;
     426  MEMORY_PROTECTION_RANGE          MemProtectionRange;
    400427
    401428  NumberOfDescriptors      = 0;
     
    534561  mSplitMemRangeCount = NumberOfSpliteRange;
    535562
     563  //
     564  // Sort the mProtectionMemRange
     565  //
     566  QuickSort (mProtectionMemRange, mProtectionMemRangeCount, sizeof (MEMORY_PROTECTION_RANGE), (BASE_SORT_COMPARE)ProtectionRangeCompare, &MemProtectionRange);
     567
    536568  DEBUG ((DEBUG_INFO, "SMM Profile Memory Ranges:\n"));
    537569  for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
     
    555587  )
    556588{
    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;
    613605  } 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
    707615  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);
    802676
    803677  //
     
    811685  mXdEnabled = TRUE;
    812686
    813   return;
     687  PERF_FUNCTION_END ();
    814688}
    815689
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h

    r99404 r101291  
    1515#include <Library/DxeServicesTableLib.h>
    1616#include <Library/CpuLib.h>
    17 #include <Library/UefiCpuLib.h>
    1817#include <IndustryStandard/Acpi.h>
    1918
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c

    r99404 r101291  
    33
    44Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
     5Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
     6
    57SPDX-License-Identifier: BSD-2-Clause-Patent
    68
     
    5052
    5153///
    52 /// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
    53 ///
    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_RANGE
    58 ///
    59 #define SMM_REGISTER_RANGE(Start, End)  { Start, End, End - Start + 1 }
    60 
    61 ///
    62 /// Structure used to describe a range of registers
    63 ///
    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 offsets
    72 /// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
    73 ///
    74 
    75 #define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX   1
    76 #define SMM_SAVE_STATE_REGISTER_IOMISC_INDEX     2
    77 #define SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX  3
    78 #define SMM_SAVE_STATE_REGISTER_MAX_INDEX        4
    79 
    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 information
    91 ///
    92 typedef struct {
    93   UINT8                          Width;
    94   EFI_SMM_SAVE_STATE_IO_WIDTH    IoWidth;
    95 } CPU_SMM_SAVE_STATE_IO_WIDTH;
    96 
    97 ///
    9854/// Variables from SMI Handler
    9955///
     
    11066
    11167///
    112 /// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
    113 /// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
    114 ///
    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 each
    124 /// supported EFI_SMM_SAVE_STATE_REGISTER value
    125 ///
    126 CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY  mSmmCpuWidthOffset[] = {
    127   { 0, 0, 0,                              0,                                   0,                                   FALSE },  //  Reserved
    128 
    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  = 1
    133   { 4, 4, SMM_CPU_OFFSET (x86.IOMisc),    SMM_CPU_OFFSET (x64.IOMisc),         0,                                   FALSE }, // SMM_SAVE_STATE_REGISTER_IOMISC_INDEX    = 2
    134   { 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 = 3
    135 
    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  = 4
    140   { 0, 8, 0,                              SMM_CPU_OFFSET (x64.IdtBaseLoDword), SMM_CPU_OFFSET (x64.IdtBaseHiDword), FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_IDTBASE  = 5
    141   { 0, 8, 0,                              SMM_CPU_OFFSET (x64.LdtBaseLoDword), SMM_CPU_OFFSET (x64.LdtBaseHiDword), FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_LDTBASE  = 6
    142   { 0, 0, 0,                              0,                                   0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
    143   { 0, 0, 0,                              0,                                   0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
    144   { 0, 0, 0,                              0,                                   0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
    145   { 0, 0, 0,                              0,                                   0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_LDTINFO  = 10
    146 
    147   { 4, 4, SMM_CPU_OFFSET (x86._ES),       SMM_CPU_OFFSET (x64._ES),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_ES       = 20
    148   { 4, 4, SMM_CPU_OFFSET (x86._CS),       SMM_CPU_OFFSET (x64._CS),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CS       = 21
    149   { 4, 4, SMM_CPU_OFFSET (x86._SS),       SMM_CPU_OFFSET (x64._SS),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_SS       = 22
    150   { 4, 4, SMM_CPU_OFFSET (x86._DS),       SMM_CPU_OFFSET (x64._DS),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_DS       = 23
    151   { 4, 4, SMM_CPU_OFFSET (x86._FS),       SMM_CPU_OFFSET (x64._FS),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_FS       = 24
    152   { 4, 4, SMM_CPU_OFFSET (x86._GS),       SMM_CPU_OFFSET (x64._GS),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_GS       = 25
    153   { 0, 4, 0,                              SMM_CPU_OFFSET (x64._LDTR),          0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
    154   { 4, 4, SMM_CPU_OFFSET (x86._TR),       SMM_CPU_OFFSET (x64._TR),            0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_TR_SEL   = 27
    155   { 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      = 28
    156   { 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      = 29
    157   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R8),            SMM_CPU_OFFSET (x64._R8)     + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R8       = 30
    158   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R9),            SMM_CPU_OFFSET (x64._R9)     + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R9       = 31
    159   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R10),           SMM_CPU_OFFSET (x64._R10)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R10      = 32
    160   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R11),           SMM_CPU_OFFSET (x64._R11)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R11      = 33
    161   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R12),           SMM_CPU_OFFSET (x64._R12)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R12      = 34
    162   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R13),           SMM_CPU_OFFSET (x64._R13)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R13      = 35
    163   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R14),           SMM_CPU_OFFSET (x64._R14)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R14      = 36
    164   { 0, 8, 0,                              SMM_CPU_OFFSET (x64._R15),           SMM_CPU_OFFSET (x64._R15)    + 4,    TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R15      = 37
    165   { 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      = 38
    166   { 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      = 39
    167   { 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      = 40
    168   { 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      = 41
    169   { 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      = 42
    170   { 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      = 43
    171   { 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      = 44
    172   { 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      = 45
    173   { 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      = 46
    174 
    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   = 51
    176   { 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      = 52
    177   { 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      = 53
    178   { 0, 4, 0,                              SMM_CPU_OFFSET (x64._CR4),           0,                                   FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CR4      = 54
    179 };
    180 
    181 ///
    182 /// Lookup table for the IOMisc width information
    183 ///
    184 CONST CPU_SMM_SAVE_STATE_IO_WIDTH  mSmmCpuIoWidth[] = {
    185   { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 0
    186   { 1, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // SMM_IO_LENGTH_BYTE  = 1
    187   { 2, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 },  // SMM_IO_LENGTH_WORD  = 2
    188   { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 3
    189   { 4, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 },  // SMM_IO_LENGTH_DWORD = 4
    190   { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 5
    191   { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 6
    192   { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  }   // Undefined           = 7
    193 };
    194 
    195 ///
    196 /// Lookup table for the IOMisc type information
    197 ///
    198 CONST EFI_SMM_SAVE_STATE_IO_TYPE  mSmmCpuIoType[] = {
    199   EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT,     // SMM_IO_TYPE_OUT_DX        = 0
    200   EFI_SMM_SAVE_STATE_IO_TYPE_INPUT,      // SMM_IO_TYPE_IN_DX         = 1
    201   EFI_SMM_SAVE_STATE_IO_TYPE_STRING,     // SMM_IO_TYPE_OUTS          = 2
    202   EFI_SMM_SAVE_STATE_IO_TYPE_STRING,     // SMM_IO_TYPE_INS           = 3
    203   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 4
    204   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 5
    205   EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS      = 6
    206   EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS       = 7
    207   EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT,     // SMM_IO_TYPE_OUT_IMMEDIATE = 8
    208   EFI_SMM_SAVE_STATE_IO_TYPE_INPUT,      // SMM_IO_TYPE_OUT_IMMEDIATE = 9
    209   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 10
    210   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 11
    211   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 12
    212   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 13
    213   (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 14
    214   (EFI_SMM_SAVE_STATE_IO_TYPE)0          // Undefined                 = 15
    215 };
    216 
    217 ///
    21868/// The mode of the CPU at the time an SMI occurs
    21969///
    22070UINT8  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 valid
    228   @retval >0  Index into mSmmCpuWidthOffset[] associated with Register
    229 
    230 **/
    231 UINTN
    232 GetRegisterIndex (
    233   IN EFI_SMM_SAVE_STATE_REGISTER  Register
    234   )
    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 the
    254   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_STATUS
    269 ReadSaveStateRegisterByIndex (
    270   IN UINTN  CpuIndex,
    271   IN UINTN  RegisterIndex,
    272   IN UINTN  Width,
    273   OUT VOID  *Buffer
    274   )
    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 accessed
    287     //
    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 accessed
    294     //
    295     if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
    296       return EFI_INVALID_PARAMETER;
    297     }
    298 
    299     //
    300     // Write return buffer
    301     //
    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 accessed
    307     //
    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 accessed
    314     //
    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 buffer
    321     //
    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 buffer
    326       //
    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 the
    338   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_STATUS
    353 EFIAPI
    354 ReadSaveStateRegister (
    355   IN UINTN                        CpuIndex,
    356   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    357   IN UINTN                        Width,
    358   OUT VOID                        *Buffer
    359   )
    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_LMA
    367   //
    368   if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
    369     //
    370     // Only byte access is supported for this register
    371     //
    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_IO
    383   //
    384   if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
    385     //
    386     // Get SMM Revision ID
    387     //
    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 state
    392     //
    393     if (SmmRevId < SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC) {
    394       return EFI_NOT_FOUND;
    395     }
    396 
    397     //
    398     // Get the IOMisc register value
    399     //
    400     ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof (IoMisc.Uint32), &IoMisc.Uint32);
    401 
    402     //
    403     // Check for the SMI_FLAG in IOMisc
    404     //
    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 tables
    420     //
    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 accessing
    427     //
    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 Buffer
    434     //
    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 structure
    440     //
    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 index
    450   //
    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 the
    458   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_STATUS
    473 EFIAPI
    474 WriteSaveStateRegister (
    475   IN UINTN                        CpuIndex,
    476   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    477   IN UINTN                        Width,
    478   IN CONST VOID                   *Buffer
    479   )
    480 {
    481   UINTN                 RegisterIndex;
    482   SMRAM_SAVE_STATE_MAP  *CpuSaveState;
    483 
    484   //
    485   // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
    486   //
    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 supported
    493   //
    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 index
    500   //
    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 mode
    517   //
    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 accessed
    521     //
    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 accessed
    528     //
    529     if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
    530       return EFI_INVALID_PARAMETER;
    531     }
    532 
    533     //
    534     // Write SMM State register
    535     //
    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 accessed
    541     //
    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 accessed
    548     //
    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 register
    555     //
    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 register
    560       //
    561       CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
    562     }
    563   }
    564 
    565   return EFI_SUCCESS;
    566 }
    56771
    56872/**
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c

    r99404 r101291  
    22Page Fault (#PF) handler for X64 processors
    33
    4 Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
    55Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
    66
     
    1313#define PAGE_TABLE_PAGES  8
    1414#define ACC_MAX_BIT       BIT3
    15 
    16 extern UINTN  mSmmShadowStackSize;
    1715
    1816LIST_ENTRY                mPagePool           = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool);
     
    171169
    172170/**
    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 VOID
    179 SetStaticPageTable (
    180   IN UINTN  PageTable,
    181   IN UINT8  PhysicalAddressBits
    182   )
    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 addresses
    201   //  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 = 0
    241         ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded
    242         ; 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 entries
    279             //
    280             continue;
    281           }
    282 
    283           //
    284           // Fill in the Page Directory entries
    285           //
    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 entries
    294             //
    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 Entries
    310             //
    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 entries
    317             //
    318             *PageDirectoryEntry = PageAddress | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;
    319           }
    320         }
    321       }
    322     }
    323   }
    324 }
    325 
    326 /**
    327171  Create PageTable for SMM use.
    328172
     
    335179  )
    336180{
    337   EFI_PHYSICAL_ADDRESS      Pages;
    338   UINT64                    *PTEntry;
     181  UINTN                     PageTable;
    339182  LIST_ENTRY                *FreePage;
    340183  UINTN                     Index;
     
    342185  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
    343186  EFI_STATUS                Status;
     187  UINT64                    *PdptEntry;
    344188  UINT64                    *Pml4Entry;
    345189  UINT64                    *Pml5Entry;
     190  UINT8                     PhysicalAddressBits;
    346191
    347192  //
     
    355200  mPhysicalAddressBits          = CalculateMaximumSupportAddress ();
    356201  PatchInstructionX86 (gPatch5LevelPagingNeeded, m5LevelPagingNeeded, 1);
     202  if (m5LevelPagingNeeded) {
     203    mPagingMode = m1GPageTableSupport ? Paging5Level1GB : Paging5Level;
     204  } else {
     205    mPagingMode = m1GPageTableSupport ? Paging4Level1GB : Paging4Level;
     206  }
     207
    357208  DEBUG ((DEBUG_INFO, "5LevelPaging Needed             - %d\n", m5LevelPagingNeeded));
    358209  DEBUG ((DEBUG_INFO, "1GPageTable Support             - %d\n", m1GPageTableSupport));
    359210  DEBUG ((DEBUG_INFO, "PcdCpuSmmRestrictedMemoryAccess - %d\n", mCpuSmmRestrictedMemoryAccess));
    360211  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);
    370235  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
    410245    //
    411246    // Add pages to page pool
     
    464299  // Return the address of PML4/PML5 (to set CR3)
    465300  //
    466   return (UINT32)(UINTN)PTEntry;
     301  return (UINT32)PageTable;
    467302}
    468303
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c

    r99404 r101291  
    22  SMM CPU misc functions for x64 arch specific.
    33
    4 Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
    55SPDX-License-Identifier: BSD-2-Clause-Patent
    66
     
    1313
    1414extern BOOLEAN  mCetSupported;
    15 extern UINTN    mSmmShadowStackSize;
    1615
    1716X86_ASSEMBLY_PATCH_LABEL  mPatchCetPl0Ssp;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c

    r99404 r101291  
    3636  )
    3737{
    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
    5540  // Return the address of PML4 (to set CR3)
    5641  //
    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);
    5846
    5947  return;
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm

    r80721 r101291  
    33; Sets the CR3 register for 64-bit paging
    44;
    5 ; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
     5; Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR>
    66; SPDX-License-Identifier: BSD-2-Clause-Patent
    77;
     
    1818    ; These pages are built into the ROM image in X64/PageTables.asm
    1919    ;
    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)
    2131    mov     cr3, eax
     32    mov     eax, cr4
     33    bts     eax, 12                     ; Set LA57=1.
     34    mov     cr4, eax
     35    jmp     SetCr3Done
     36NotSupport5LevelPaging:
     37%endif
     38
     39    mov     eax, ADDR_OF(Pml4)
     40    mov     cr3, eax
     41SetCr3Done:
    2242
    2343    OneTimeCallRet SetCr3ForPageTables64
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/ReadMe.txt

    r99404 r101291  
    11
    22=== HOW TO USE VTF0 ===
     3Add this line to your DSC [Components.IA32] or [Components.X64] section:
     4  UefiCpuPkg/ResetVector/Vtf0/ResetVector.inf
    35
    46Add 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
    78
    89In your FDF FFS file rules sections add:
    9 [Rule.Common.SEC.RESET_VECTOR]
    10   FILE RAW = $(NAMED_GUID) {
    11     RAW RAW                |.raw
    12   }
     10  [Rule.Common.SEC.RESET_VECTOR]
     11    FILE RAW = $(NAMED_GUID) {
     12      RAW BIN   |.bin
     13    }
    1314
    1415=== VTF0 Boot Flow ===
     
    2627DI      - 'BP': boot-strap processor, or 'AP': application processor
    2728EBP/RBP - Pointer to the start of the Boot Firmware Volume
    28 
    29 === HOW TO BUILD VTF0 ===
    30 
    31 Dependencies:
    32 * Python 3 or newer
    33 * Nasm 2.03 or newer
    34 
    35 To rebuild the VTF0 binaries:
    36 1. Change to VTF0 source dir: UefiCpuPkg/ResetVector/Vtf0
    37 2. nasm and python should be in executable path
    38 3. Run this command:
    39    python Build.py
    40 4. Binaries output will be in UefiCpuPkg/ResetVector/Vtf0/Bin
    41 
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf

    r80721 r101291  
    22#  Reset Vector
    33#
    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>
    522#
    623#  SPDX-License-Identifier: BSD-2-Clause-Patent
     
    3047[UserExtensions.TianoCore."ExtraFiles"]
    3148  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  
    33; This file includes all other code files to assemble the reset vector code
    44;
    5 ; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
     5; Copyright (c) 2008 - 2023, Intel Corporation. All rights reserved.<BR>
    66; SPDX-License-Identifier: BSD-2-Clause-Patent
    77;
     
    3939
    4040%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"
    4642%endif
    4743
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecCore.inf

    r99404 r101291  
    4949  DebugAgentLib
    5050  CpuLib
    51   UefiCpuLib
    5251  PeCoffGetEntryPointLib
    5352  PeCoffExtraActionLib
     
    5756  PeiServicesTablePointerLib
    5857  HobLib
     58  CpuPageTableLib
    5959
    6060[Ppis]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecCoreNative.inf

    r99404 r101291  
    4646  DebugAgentLib
    4747  CpuLib
    48   UefiCpuLib
    4948  PeCoffGetEntryPointLib
    5049  PeCoffExtraActionLib
     
    5453  PeiServicesTablePointerLib
    5554  HobLib
     55  CpuPageTableLib
    5656
    5757[Ppis]
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecMain.c

    r99404 r101291  
    7171
    7272  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**/
     83EFI_STATUS
     84MigratePageTable (
     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;
    73202}
    74203
     
    171300    DEBUG_INFO,
    172301    "%a() TempRAM Base: 0x%x, TempRAM Size: 0x%x, BootFirmwareVolume 0x%x\n",
    173     __FUNCTION__,
     302    __func__,
    174303    TempRamBase,
    175304    SizeOfRam,
     
    243372    DEBUG_INFO,
    244373    "%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__,
    246375    SecCoreData.BootFirmwareVolumeBase,
    247376    SecCoreData.BootFirmwareVolumeSize,
     
    346475    DEBUG_INFO,
    347476    "%a() PeiCoreEntryPoint: 0x%x\n",
    348     __FUNCTION__,
     477    __func__,
    349478    PeiCoreEntryPoint
    350479    ));
     
    395524      DEBUG_INFO,
    396525      "%a() PeiTemporaryRamBase: 0x%x, PeiTemporaryRamSize: 0x%x\n",
    397       __FUNCTION__,
     526      __func__,
    398527      SecCoreData->PeiTemporaryRamBase,
    399528      SecCoreData->PeiTemporaryRamSize
     
    409538    DEBUG_INFO,
    410539    "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
    411     __FUNCTION__,
     540    __func__,
    412541    SecCoreData->StackBase,
    413542    (UINT32)SecCoreData->StackSize
     
    454583  EFI_PEI_PPI_DESCRIPTOR  *PeiPpiDescriptor;
    455584  REPUBLISH_SEC_PPI_PPI   *RepublishSecPpiPpi;
     585  IA32_CR0                Cr0;
    456586
    457587  //
     
    496626
    497627  //
     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  //
    498645  // Disable Temporary RAM after Stack and Heap have been migrated at this point.
    499646  //
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/SecCore/SecMain.h

    r99404 r101291  
    2020#include <Guid/FirmwarePerformance.h>
    2121
     22#include <Library/BaseLib.h>
    2223#include <Library/DebugLib.h>
    2324#include <Library/PcdLib.h>
     
    2526#include <Library/PlatformSecLib.h>
    2627#include <Library/CpuLib.h>
    27 #include <Library/UefiCpuLib.h>
    2828#include <Library/PeCoffGetEntryPointLib.h>
    2929#include <Library/PeCoffExtraActionLib.h>
     
    3434#include <Library/HobLib.h>
    3535#include <Library/PeiServicesLib.h>
     36#include <Library/CpuPageTableLib.h>
     37#include <Register/Intel/Cpuid.h>
     38#include <Register/Intel/Msr.h>
    3639
    3740#define SEC_IDT_ENTRY_COUNT  34
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c

    r99404 r101291  
    4646  Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber);
    4747  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));
    4949
    5050  Status = MpServicesUnitTestGetNumberOfProcessors (
     
    5757    DEBUG_INFO,
    5858    "%a: NumberOfProcessors = 0x%x, NumberOfEnabledProcessors = 0x%x\n",
    59     __FUNCTION__,
     59    __func__,
    6060    NumberOfProcessors,
    6161    NumberOfEnabledProcessors
     
    9090        IndexOfDisabledAPs++;
    9191
    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));
    9393        Status = MpServicesUnitTestEnableDisableAP (
    9494                   LocalContext->MpServices,
     
    135135  if (BspNumber != LocalContext->BspNumber) {
    136136    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));
    138138  }
    139139
     
    149149  if (NumberOfProcessors != LocalContext->NumberOfProcessors) {
    150150    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));
    152152  }
    153153
    154154  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));
    156156
    157157    for (ProcessorNumber = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) {
     
    164164
    165165      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));
    167167        Status = MpServicesUnitTestEnableDisableAP (
    168168                   LocalContext->MpServices,
     
    205205        DEBUG_INFO,
    206206        "%a: Disable AP(0x%x) to restore its state.\n",
    207         __FUNCTION__,
     207        __func__,
    208208        LocalContext->DisabledApNumber[IndexOfDisabledAPs]
    209209        ));
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/UefiCpuPkg.dec

    r99404 r101291  
    22# This Package provides UEFI compatible CPU modules and libraries.
    33#
    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>
    56#
    67# SPDX-License-Identifier: BSD-2-Clause-Patent
     
    1920
    2021[LibraryClasses]
    21   ##  @libraryclass  Defines some routines that are generic for IA32 family CPU
    22   ##                 to be UEFI specification compliant.
    23   ##
    24   UefiCpuLib|Include/Library/UefiCpuLib.h
    25 
    2622  ##  @libraryclass  Defines some routines that are used to register/manage/program
    2723  ##                 CPU features.
     
    6561  ##  @libraryclass  Provides function for manipulating x86 paging structures.
    6662  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
    6771
    6872[Guids]
     
    7882  ## Include/Guid/MicrocodePatchHob.h
    7983  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 }}
    8087
    8188[Protocols]
     
    178185  gUefiCpuPkgTokenSpaceGuid.PcdSmmFeatureControlEnable|TRUE|BOOLEAN|0x32132110
    179186
     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
    180193[PcdsFixedAtBuild]
    181194  ## List of exception vectors which need switching stack.
     
    201214  # @Prompt Configure the SEV-ES work area base
    202215  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
    203227
    204228[PcdsFixedAtBuild, PcdsPatchableInModule]
     
    341365  gUefiCpuPkgTokenSpaceGuid.PcdIsPowerOnReset|FALSE|BOOLEAN|0x0000001B
    342366
     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
    343382[PcdsFixedAtBuild.X64, PcdsPatchableInModule.X64, PcdsDynamic.X64, PcdsDynamicEx.X64]
    344383  ## 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  
    22#  UefiCpuPkg Package
    33#
    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>
    56#
    67#  SPDX-License-Identifier: BSD-2-Clause-Patent
     
    3233  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
    3334  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
    34   UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
    3535  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
    3636  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
     
    7070[LibraryClasses.common.SEC]
    7171  PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
    72 !if $(TOOL_CHAIN_TAG) == "XCODE5"
    73   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
    74 !else
    7572  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
    76 !endif
    7773  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
    7874  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
     
    105101  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
    106102  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
     103  MmSaveStateLib|UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveStateLib.inf
    107104
    108105[LibraryClasses.common.MM_STANDALONE]
     
    141138  UefiCpuPkg/CpuMpPei/CpuMpPei.inf
    142139  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
    143   UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
    144140  UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
    145141  UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
    146142  UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf
    147143  UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
    148 !if $(TOOL_CHAIN_TAG) != "XCODE5"
    149144  UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
    150 !endif
    151145  UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
    152146  UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
    153   UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
    154147  UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
    155148  UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
     
    177170      SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
    178171  }
     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  }
    179179  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
    180   UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
     180  UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
    181181  UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
    182182  UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
     
    192192      UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.inf
    193193  }
     194  UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
     195  UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveStateLib.inf
     196  UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf
    194197
    195198[Components.X64]
     
    199202  UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandlerLib/BaseRiscV64CpuExceptionHandlerLib.inf
    200203  UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf
     204  UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf
    201205  UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf
    202206  UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf
  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c

    r99404 r101291  
    510510      DEBUG_INFO,
    511511      "%a() Stack Base: 0x%x, Stack Size: 0x%x\n",
    512       __FUNCTION__,
     512      __func__,
    513513      TempStackTop,
    514514      sizeof (TempStack)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette