SecCcExitVcHandler.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /** @file
  2. X64 #VC Exception Handler functon.
  3. Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Uefi.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/MemEncryptSevLib.h>
  10. #include <Library/CcExitLib.h>
  11. #include <Register/Amd/Msr.h>
  12. #include "CcExitVcHandler.h"
  13. /**
  14. Handle a #VC exception.
  15. Performs the necessary processing to handle a #VC exception.
  16. @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
  17. as value to use on error.
  18. @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
  19. @retval EFI_SUCCESS Exception handled
  20. @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
  21. propagate provided
  22. @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
  23. propagate provided
  24. **/
  25. EFI_STATUS
  26. EFIAPI
  27. VmgExitHandleVc (
  28. IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
  29. IN OUT EFI_SYSTEM_CONTEXT SystemContext
  30. )
  31. {
  32. MSR_SEV_ES_GHCB_REGISTER Msr;
  33. GHCB *Ghcb;
  34. GHCB *GhcbBackup;
  35. EFI_STATUS VcRet;
  36. BOOLEAN InterruptState;
  37. SEV_ES_PER_CPU_DATA *SevEsData;
  38. InterruptState = GetInterruptState ();
  39. if (InterruptState) {
  40. DisableInterrupts ();
  41. }
  42. Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
  43. ASSERT (Msr.GhcbInfo.Function == 0);
  44. ASSERT (Msr.Ghcb != 0);
  45. Ghcb = Msr.Ghcb;
  46. GhcbBackup = NULL;
  47. SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
  48. SevEsData->VcCount++;
  49. //
  50. // Check for maximum SEC #VC nesting.
  51. //
  52. if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
  53. VmgExitIssueAssert (SevEsData);
  54. } else if (SevEsData->VcCount > 1) {
  55. UINTN GhcbBackupSize;
  56. //
  57. // Be sure that the proper amount of pages are allocated
  58. //
  59. GhcbBackupSize = (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb);
  60. if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) {
  61. //
  62. // Not enough SEC backup pages allocated.
  63. //
  64. VmgExitIssueAssert (SevEsData);
  65. }
  66. //
  67. // Save the active GHCB to a backup page.
  68. // To access the correct backup page, increment the backup page pointer
  69. // based on the current VcCount.
  70. //
  71. GhcbBackup = (GHCB *)FixedPcdGet32 (PcdOvmfSecGhcbBackupBase);
  72. GhcbBackup += (SevEsData->VcCount - 2);
  73. CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
  74. }
  75. VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
  76. if (GhcbBackup != NULL) {
  77. //
  78. // Restore the active GHCB from the backup page.
  79. //
  80. CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
  81. }
  82. SevEsData->VcCount--;
  83. if (InterruptState) {
  84. EnableInterrupts ();
  85. }
  86. return VcRet;
  87. }