3 Unaccepted memory is a special type of private memory. In Td guest
4 TDCALL [TDG.MEM.PAGE.ACCEPT] is invoked to accept the unaccepted
7 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseLib.h>
13 #include <Library/DebugLib.h>
14 #include <IndustryStandard/Tdx.h>
15 #include <Uefi/UefiBaseType.h>
16 #include <Library/TdxLib.h>
17 #include <Library/BaseMemoryLib.h>
19 UINT64 mNumberOfDuplicatedAcceptedPages
;
21 #define TDX_ACCEPTPAGE_MAX_RETRIED 3
23 // PageSize is mapped to PageLevel like below:
25 UINT32 mTdxAcceptPageLevelMap
[2] = {
30 #define INVALID_ACCEPT_PAGELEVEL ARRAY_SIZE(mTdxAcceptPageLevelMap)
33 This function gets the PageLevel according to the input page size.
35 @param[in] PageSize Page size
37 @return UINT32 The mapped page level
46 for (Index
= 0; Index
< ARRAY_SIZE (mTdxAcceptPageLevelMap
); Index
++) {
47 if (mTdxAcceptPageLevelMap
[Index
] == PageSize
) {
56 This function accept a pending private page, and initialize the page to
57 all-0 using the TD ephemeral private key.
59 Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return
60 TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel is
61 not workable. In this case we need to try to fallback to a smaller
62 PageLevel if possible.
64 @param[in] StartAddress Guest physical address of the private
65 page to accept. [63:52] and [11:0] must be 0.
66 @param[in] NumberOfPages Number of the pages to be accepted.
67 @param[in] PageSize GPA page size. Only accept 2M/4K size.
69 @return EFI_SUCCESS Accept successfully
70 @return others Indicate other errors
75 IN UINT64 StartAddress
,
76 IN UINT64 NumberOfPages
,
90 if ((StartAddress
& ~0xFFFFFFFFFF000ULL
) != 0) {
92 DEBUG ((DEBUG_ERROR
, "Accept page address(0x%llx) is not valid. [63:52] and [11:0] must be 0\n", StartAddress
));
93 return EFI_INVALID_PARAMETER
;
96 Address
= StartAddress
;
98 GpaPageLevel
= GetGpaPageLevel (PageSize
);
99 if (GpaPageLevel
== INVALID_ACCEPT_PAGELEVEL
) {
101 DEBUG ((DEBUG_ERROR
, "Accept page size must be 4K/2M. Invalid page size - 0x%llx\n", PageSize
));
102 return EFI_INVALID_PARAMETER
;
105 Status
= EFI_SUCCESS
;
106 for (Index
= 0; Index
< NumberOfPages
; Index
++) {
110 TdxStatus
= TdCall (TDCALL_TDACCEPTPAGE
, Address
| GpaPageLevel
, 0, 0, 0);
111 if (TdxStatus
!= TDX_EXIT_REASON_SUCCESS
) {
112 if ((TdxStatus
& ~0xFFFFULL
) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED
) {
116 mNumberOfDuplicatedAcceptedPages
++;
117 DEBUG ((DEBUG_WARN
, "Page at Address (0x%llx) has already been accepted. - %d\n", Address
, mNumberOfDuplicatedAcceptedPages
));
118 } else if ((TdxStatus
& ~0xFFFFULL
) == TDX_EXIT_REASON_PAGE_SIZE_MISMATCH
) {
120 // GpaPageLevel is mismatch, fall back to a smaller GpaPageLevel if possible
122 DEBUG ((DEBUG_VERBOSE
, "Address %llx cannot be accepted in PageLevel of %d\n", Address
, GpaPageLevel
));
124 if (GpaPageLevel
== 0) {
126 // Cannot fall back to smaller page level
128 DEBUG ((DEBUG_ERROR
, "AcceptPage cannot fallback from PageLevel %d\n", GpaPageLevel
));
129 Status
= EFI_INVALID_PARAMETER
;
133 // Fall back to a smaller page size
135 PageSize2
= mTdxAcceptPageLevelMap
[GpaPageLevel
- 1];
136 Status
= TdAcceptPages (Address
, 512, PageSize2
);
137 if (EFI_ERROR (Status
)) {
141 } else if ((TdxStatus
& ~0xFFFFULL
) == TDX_EXIT_REASON_OPERAND_BUSY
) {
143 // Concurrent TDG.MEM.PAGE.ACCEPT is using the same Secure EPT entry
144 // So try it again. There is a max retried count. If Retried exceeds the max count,
145 // report the error and quit.
148 if (Retried
> TDX_ACCEPTPAGE_MAX_RETRIED
) {
151 "Address %llx (%d) failed to be accepted because of OPERAND_BUSY. Retried %d time.\n",
156 Status
= EFI_INVALID_PARAMETER
;
167 "Address %llx (%d) failed to be accepted. Error = 0x%llx\n",
172 Status
= EFI_INVALID_PARAMETER
;