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