FeatureControl.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**@file
  2. Install a callback when necessary for setting the Feature Control MSR on all
  3. processors.
  4. Copyright (C) 2016, Red Hat, Inc.
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Library/DebugLib.h>
  8. #include <Library/HobLib.h>
  9. #include <Library/PeiServicesLib.h>
  10. #include <Library/QemuFwCfgLib.h>
  11. #include <Ppi/MpServices.h>
  12. #include <Register/ArchitecturalMsr.h>
  13. #include <IndustryStandard/Tdx.h>
  14. #include "Platform.h"
  15. /**
  16. Write the Feature Control MSR on an Application Processor or the Boot
  17. Processor.
  18. All APs execute this function in parallel. The BSP executes the function
  19. separately.
  20. @param[in,out] WorkSpace Pointer to the input/output argument workspace
  21. shared by all processors.
  22. **/
  23. STATIC
  24. VOID
  25. EFIAPI
  26. WriteFeatureControl (
  27. IN OUT VOID *WorkSpace
  28. )
  29. {
  30. EFI_HOB_PLATFORM_INFO *PlatformInfoHob = WorkSpace;
  31. if (TdIsEnabled ()) {
  32. TdVmCall (
  33. TDVMCALL_WRMSR,
  34. (UINT64)MSR_IA32_FEATURE_CONTROL,
  35. PlatformInfoHob->FeatureControlValue,
  36. 0,
  37. 0,
  38. 0
  39. );
  40. } else {
  41. AsmWriteMsr64 (
  42. MSR_IA32_FEATURE_CONTROL,
  43. PlatformInfoHob->FeatureControlValue
  44. );
  45. }
  46. }
  47. /**
  48. Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
  49. @param[in] PeiServices Indirect reference to the PEI Services Table.
  50. @param[in] NotifyDescriptor Address of the notification descriptor data
  51. structure.
  52. @param[in] Ppi Address of the PPI that was installed.
  53. @return Status of the notification. The status code returned from this
  54. function is ignored.
  55. **/
  56. STATIC
  57. EFI_STATUS
  58. EFIAPI
  59. OnMpServicesAvailable (
  60. IN EFI_PEI_SERVICES **PeiServices,
  61. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  62. IN VOID *Ppi
  63. )
  64. {
  65. EFI_PEI_MP_SERVICES_PPI *MpServices;
  66. EFI_STATUS Status;
  67. EFI_HOB_PLATFORM_INFO *PlatformInfoHob;
  68. EFI_HOB_GUID_TYPE *GuidHob;
  69. GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
  70. if (GuidHob == NULL) {
  71. return EFI_UNSUPPORTED;
  72. }
  73. PlatformInfoHob = (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);
  74. DEBUG ((DEBUG_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
  75. //
  76. // Write the MSR on all the APs in parallel.
  77. //
  78. MpServices = Ppi;
  79. Status = MpServices->StartupAllAPs (
  80. (CONST EFI_PEI_SERVICES **)PeiServices,
  81. MpServices,
  82. WriteFeatureControl, // Procedure
  83. FALSE, // SingleThread
  84. 0, // TimeoutInMicroSeconds: inf.
  85. PlatformInfoHob // ProcedureArgument
  86. );
  87. if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
  88. DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
  89. return Status;
  90. }
  91. //
  92. // Now write the MSR on the BSP too.
  93. //
  94. WriteFeatureControl (PlatformInfoHob);
  95. return EFI_SUCCESS;
  96. }
  97. //
  98. // Notification object for registering the callback, for when
  99. // EFI_PEI_MP_SERVICES_PPI becomes available.
  100. //
  101. STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
  102. EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
  103. EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  104. &gEfiPeiMpServicesPpiGuid, // Guid
  105. OnMpServicesAvailable // Notify
  106. };
  107. VOID
  108. InstallFeatureControlCallback (
  109. IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
  110. )
  111. {
  112. EFI_STATUS Status;
  113. FIRMWARE_CONFIG_ITEM FwCfgItem;
  114. UINTN FwCfgSize;
  115. Status = QemuFwCfgFindFile (
  116. "etc/msr_feature_control",
  117. &FwCfgItem,
  118. &FwCfgSize
  119. );
  120. if (EFI_ERROR (Status) || (FwCfgSize != sizeof (PlatformInfoHob->FeatureControlValue))) {
  121. //
  122. // Nothing to do.
  123. //
  124. return;
  125. }
  126. QemuFwCfgSelectItem (FwCfgItem);
  127. QemuFwCfgReadBytes (
  128. sizeof (PlatformInfoHob->FeatureControlValue),
  129. &(PlatformInfoHob->FeatureControlValue)
  130. );
  131. Status = PeiServicesNotifyPpi (&mMpServicesNotify);
  132. if (EFI_ERROR (Status)) {
  133. DEBUG ((
  134. DEBUG_ERROR,
  135. "%a: failed to set up MP Services callback: %r\n",
  136. __FUNCTION__,
  137. Status
  138. ));
  139. }
  140. }