From 5a0932b7d480c05761a3ba9b5cf1d2fbb470c615 Mon Sep 17 00:00:00 2001 From: Nickle Wang Date: Wed, 1 Mar 2023 16:44:57 +0800 Subject: [PATCH 01/16] RedfishPkg/RedfishDebugLib: provide Redfish debug Introduce RedfishDebugLib to RedfishPkg. This library provides several debugging functions for Redfish application. Redfish drivers rely on Rest Ex protocol to communicate with BMC and the communication data may be big and complicated. Use RedfishDebugLib in RedfishRestExDxe to simplify debugging process. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Igor Kulchytskyy Cc: Nick Ramirez Reviewed-by: Abner Chang --- RedfishPkg/Include/Library/RedfishDebugLib.h | 90 +++++++ .../Library/RedfishDebugLib/RedfishDebugLib.c | 229 ++++++++++++++++++ .../RedfishDebugLib/RedfishDebugLib.inf | 39 +++ RedfishPkg/RedfishLibs.dsc.inc | 2 + RedfishPkg/RedfishPkg.dec | 5 + RedfishPkg/RedfishPkg.dsc | 1 + .../RedfishRestExDxe/RedfishRestExDxe.inf | 2 + .../RedfishRestExDxe/RedfishRestExInternal.h | 2 + .../RedfishRestExDxe/RedfishRestExProtocol.c | 32 +-- 9 files changed, 387 insertions(+), 15 deletions(-) create mode 100644 RedfishPkg/Include/Library/RedfishDebugLib.h create mode 100644 RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.c create mode 100644 RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf diff --git a/RedfishPkg/Include/Library/RedfishDebugLib.h b/RedfishPkg/Include/Library/RedfishDebugLib.h new file mode 100644 index 0000000000..21f01353ed --- /dev/null +++ b/RedfishPkg/Include/Library/RedfishDebugLib.h @@ -0,0 +1,90 @@ +/** @file + This file defines the Redfish debug library interface. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef REDFISH_DEBUG_LIB_H_ +#define REDFISH_DEBUG_LIB_H_ + +#include +#include +#include + +#define DEBUG_REDFISH_NETWORK DEBUG_INFO ///< Debug error level for Redfish networking function + +/** + + This function dump the Json string in given error level. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] JsonValue Json value to dump. + + @retval EFI_SUCCESS Json string is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpJsonValue ( + IN UINTN ErrorLevel, + IN EDKII_JSON_VALUE JsonValue + ); + +/** + + This function dump the status code, header and body in given + Redfish payload. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] Payload Redfish payload to dump + + @retval EFI_SUCCESS Redfish payload is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpRedfishPayload ( + IN UINTN ErrorLevel, + IN REDFISH_PAYLOAD Payload + ); + +/** + + This function dump the status code, header and body in given + Redfish response. + + @param[in] Message Message string + @param[in] ErrorLevel DEBUG macro error level + @param[in] Response Redfish response to dump + + @retval EFI_SUCCESS Redfish response is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpRedfishResponse ( + IN CONST CHAR8 *Message, + IN UINTN ErrorLevel, + IN REDFISH_RESPONSE *Response + ); + +/** + + This function dump the HTTP status code. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] HttpStatusCode HTTP status code + + @retval EFI_SUCCESS HTTP status code is printed + +**/ +EFI_STATUS +DumpHttpStatusCode ( + IN UINTN ErrorLevel, + IN EFI_HTTP_STATUS_CODE HttpStatusCode + ); + +#endif diff --git a/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.c b/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.c new file mode 100644 index 0000000000..6f1d9de25e --- /dev/null +++ b/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.c @@ -0,0 +1,229 @@ +/** @file + Redfish debug library to debug Redfish application. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +#ifndef IS_EMPTY_STRING +#define IS_EMPTY_STRING(a) ((a) == NULL || (a)[0] == '\0') +#endif + +#define REDFISH_JSON_STRING_LENGTH 200 +#define REDFISH_JSON_OUTPUT_FORMAT (EDKII_JSON_COMPACT | EDKII_JSON_INDENT(2)) + +/** + + This function dump the Json string in given error level. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] JsonValue Json value to dump. + + @retval EFI_SUCCESS Json string is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpJsonValue ( + IN UINTN ErrorLevel, + IN EDKII_JSON_VALUE JsonValue + ) +{ + CHAR8 *String; + CHAR8 *Runner; + CHAR8 Buffer[REDFISH_JSON_STRING_LENGTH + 1]; + UINTN StrLen; + UINTN Count; + UINTN Index; + + if (JsonValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + String = JsonDumpString (JsonValue, REDFISH_JSON_OUTPUT_FORMAT); + if (String == NULL) { + return EFI_UNSUPPORTED; + } + + StrLen = AsciiStrLen (String); + if (StrLen == 0) { + return EFI_UNSUPPORTED; + } + + Count = StrLen / REDFISH_JSON_STRING_LENGTH; + Runner = String; + for (Index = 0; Index < Count; Index++) { + AsciiStrnCpyS (Buffer, (REDFISH_JSON_STRING_LENGTH + 1), Runner, REDFISH_JSON_STRING_LENGTH); + Buffer[REDFISH_JSON_STRING_LENGTH] = '\0'; + DEBUG ((ErrorLevel, "%a", Buffer)); + Runner += REDFISH_JSON_STRING_LENGTH; + } + + Count = StrLen % REDFISH_JSON_STRING_LENGTH; + if (Count > 0) { + DEBUG ((ErrorLevel, "%a", Runner)); + } + + DEBUG ((ErrorLevel, "\n")); + + FreePool (String); + return EFI_SUCCESS; +} + +/** + + This function dump the status code, header and body in given + Redfish payload. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] Payload Redfish payload to dump + + @retval EFI_SUCCESS Redfish payload is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpRedfishPayload ( + IN UINTN ErrorLevel, + IN REDFISH_PAYLOAD Payload + ) +{ + EDKII_JSON_VALUE JsonValue; + + if (Payload == NULL) { + return EFI_INVALID_PARAMETER; + } + + JsonValue = RedfishJsonInPayload (Payload); + if (JsonValue != NULL) { + DEBUG ((ErrorLevel, "Payload:\n")); + DumpJsonValue (ErrorLevel, JsonValue); + } + + return EFI_SUCCESS; +} + +/** + + This function dump the HTTP status code. + + @param[in] ErrorLevel DEBUG macro error level + @param[in] HttpStatusCode HTTP status code + + @retval EFI_SUCCESS HTTP status code is printed + +**/ +EFI_STATUS +DumpHttpStatusCode ( + IN UINTN ErrorLevel, + IN EFI_HTTP_STATUS_CODE HttpStatusCode + ) +{ + switch (HttpStatusCode) { + case HTTP_STATUS_100_CONTINUE: + DEBUG ((ErrorLevel, "Status code: 100 CONTINUE\n")); + break; + case HTTP_STATUS_200_OK: + DEBUG ((ErrorLevel, "Status code: 200 OK\n")); + break; + case HTTP_STATUS_201_CREATED: + DEBUG ((ErrorLevel, "Status code: 201 CREATED\n")); + break; + case HTTP_STATUS_202_ACCEPTED: + DEBUG ((ErrorLevel, "Status code: 202 ACCEPTED\n")); + break; + case HTTP_STATUS_304_NOT_MODIFIED: + DEBUG ((ErrorLevel, "Status code: 304 NOT MODIFIED\n")); + break; + case HTTP_STATUS_400_BAD_REQUEST: + DEBUG ((ErrorLevel, "Status code: 400 BAD REQUEST\n")); + break; + case HTTP_STATUS_401_UNAUTHORIZED: + DEBUG ((ErrorLevel, "Status code: 401 UNAUTHORIZED\n")); + break; + case HTTP_STATUS_403_FORBIDDEN: + DEBUG ((ErrorLevel, "Status code: 403 FORBIDDEN\n")); + break; + case HTTP_STATUS_404_NOT_FOUND: + DEBUG ((ErrorLevel, "Status code: 404 NOT FOUND\n")); + break; + case HTTP_STATUS_405_METHOD_NOT_ALLOWED: + DEBUG ((ErrorLevel, "Status code: 405 METHOD NOT ALLOWED\n")); + break; + case HTTP_STATUS_500_INTERNAL_SERVER_ERROR: + DEBUG ((ErrorLevel, "Status code: 500 INTERNAL SERVER ERROR\n")); + break; + default: + DEBUG ((ErrorLevel, "Status code: 0x%x\n", HttpStatusCode)); + break; + } + + return EFI_SUCCESS; +} + +/** + + This function dump the status code, header and body in given + Redfish response. + + @param[in] Message Message string + @param[in] ErrorLevel DEBUG macro error level + @param[in] Response Redfish response to dump + + @retval EFI_SUCCESS Redfish response is printed. + @retval Others Errors occur. + +**/ +EFI_STATUS +DumpRedfishResponse ( + IN CONST CHAR8 *Message, + IN UINTN ErrorLevel, + IN REDFISH_RESPONSE *Response + ) +{ + UINTN Index; + + if (Response == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!IS_EMPTY_STRING (Message)) { + DEBUG ((ErrorLevel, "%a\n", Message)); + } + + // + // status code + // + if (Response->StatusCode != NULL) { + DumpHttpStatusCode (ErrorLevel, *(Response->StatusCode)); + } + + // + // header + // + if (Response->HeaderCount > 0) { + DEBUG ((ErrorLevel, "Header: %d\n", Response->HeaderCount)); + for (Index = 0; Index < Response->HeaderCount; Index++) { + DEBUG ((ErrorLevel, " %a: %a\n", Response->Headers[Index].FieldName, Response->Headers[Index].FieldValue)); + } + } + + // + // Body + // + if (Response->Payload != NULL) { + DumpRedfishPayload (ErrorLevel, Response->Payload); + } + + return EFI_SUCCESS; +} diff --git a/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf b/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf new file mode 100644 index 0000000000..048d27c6dc --- /dev/null +++ b/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf @@ -0,0 +1,39 @@ +## @file +# INF file for Redfish debug library. +# +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = RedfishDebugLib + FILE_GUID = 7F64C79F-ABD0-4446-86B5-2C1AE36168AD + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = RedfishDebugLib| DXE_DRIVER UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + RedfishDebugLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + RedfishPkg/RedfishPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + JsonLib + MemoryAllocationLib + RedfishLib + UefiLib + +[Depex] + TRUE diff --git a/RedfishPkg/RedfishLibs.dsc.inc b/RedfishPkg/RedfishLibs.dsc.inc index 56950b711f..84f52d4b27 100644 --- a/RedfishPkg/RedfishLibs.dsc.inc +++ b/RedfishPkg/RedfishLibs.dsc.inc @@ -6,6 +6,7 @@ # of EDKII network library classes. # # (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -17,5 +18,6 @@ RedfishCrtLib|RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf RedfishLib|RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf + RedfishDebugLib|RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf !endif diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec index 130e7ec260..53e52c2b00 100644 --- a/RedfishPkg/RedfishPkg.dec +++ b/RedfishPkg/RedfishPkg.dec @@ -4,6 +4,7 @@ # Copyright (c) 2019, Intel Corporation. All rights reserved.
# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
# Copyright (c) 2023, American Megatrends International LLC. +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -55,6 +56,10 @@ # RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.h + ## @libraryclass Redfish Debug Library + # Library provides Redfish debug functions. + RedfishDebugLib|Include/Library/RedfishDebugLib.h + [LibraryClasses.Common.Private] ## @libraryclass Provides the private C runtime library functions. # CRT library is currently used by edk2 JsonLib (open source diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc index 16139146ff..cf25b63cc2 100644 --- a/RedfishPkg/RedfishPkg.dsc +++ b/RedfishPkg/RedfishPkg.dsc @@ -58,5 +58,6 @@ RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf RedfishPkg/Library/JsonLib/JsonLib.inf RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf + RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf !include RedfishPkg/Redfish.dsc.inc diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf index 2f7a2188e8..64e6343bfb 100644 --- a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf @@ -4,6 +4,7 @@ # Copyright (c) 2019, Intel Corporation. All rights reserved.
# (C) Copyright 2020 Hewlett Packard Enterprise Development LP
# Copyright (c) 2023, American Megatrends International LLC. +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -44,6 +45,7 @@ PrintLib MemoryAllocationLib NetLib + RedfishDebugLib UefiLib UefiBootServicesTableLib UefiDriverEntryPoint diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h index a687c4ddb1..bca679e2cc 100644 --- a/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h @@ -3,6 +3,7 @@ Copyright (c) 2019, Intel Corporation. All rights reserved.
(C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c index 1c3deab09a..3722e1f795 100644 --- a/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c @@ -4,6 +4,7 @@ Copyright (c) 2019, Intel Corporation. All rights reserved.
(C) Copyright 2020 Hewlett Packard Enterprise Development LP
Copyright (c) 2023, American Megatrends International LLC. + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -90,12 +91,12 @@ RedfishRestExSendReceive ( MediaPresent = TRUE; NetLibDetectMedia (Instance->Service->ControllerHandle, &MediaPresent); if (!MediaPresent) { - DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No MediaPresent.\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "RedfishRestExSendReceive(): No MediaPresent.\n")); return EFI_NO_MEDIA; } - DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n")); - DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url)); + DEBUG ((DEBUG_REDFISH_NETWORK, "\nRedfishRestExSendReceive():\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url)); if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode)) { // @@ -215,7 +216,7 @@ ReSendRequest:; goto ON_EXIT; } - DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "Receiving HTTP response and headers...\n")); Status = RedfishCheckHttpReceiveStatus ( Instance, HttpIoRecvResponse ( @@ -239,12 +240,12 @@ ReSendRequest:; RequestMessage->HeaderCount--; // Minus one header count for "Expect". } - DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:", ResponseData->Response.StatusCode)); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP Response StatusCode - %d:", ResponseData->Response.StatusCode)); if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) { - DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_200_OK\n")); if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) { - DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks - %d.", ResponseData->Response.StatusCode)); + DEBUG ((DEBUG_REDFISH_NETWORK, "This is chunk transfer, start to send all chunks - %d.", ResponseData->Response.StatusCode)); SendChunkProcess++; goto ReSendRequest; } @@ -261,7 +262,7 @@ ReSendRequest:; } else if (ResponseData->Response.StatusCode == HTTP_STATUS_202_ACCEPTED) { DEBUG ((DEBUG_INFO, "HTTP_STATUS_202_ACCEPTED\n")); } else if (ResponseData->Response.StatusCode == HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) { - DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n")); Status = EFI_BAD_BUFFER_SIZE; goto ON_EXIT; @@ -271,25 +272,25 @@ ReSendRequest:; Status = EFI_ACCESS_DENIED; goto ON_EXIT; } else if (ResponseData->Response.StatusCode == HTTP_STATUS_400_BAD_REQUEST) { - DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_400_BAD_REQUEST\n")); if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) { - DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Try to send all chunks...\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "Bad request may caused by zero length chunk. Try to send all chunks...\n")); SendChunkProcess++; goto ReSendRequest; } } else if (ResponseData->Response.StatusCode == HTTP_STATUS_100_CONTINUE) { - DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_100_CONTINUE\n")); if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) { // // We get HTTP_STATUS_100_CONTINUE to send the body using chunk transfer. // - DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk transfer...\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_100_CONTINUE for chunk transfer...\n")); SendChunkProcess++; goto ReSendRequest; } if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)) { - DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n")); + DEBUG ((DEBUG_REDFISH_NETWORK, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n")); SendNonChunkProcess++; goto ReSendRequest; } @@ -313,6 +314,7 @@ ReSendRequest:; } } else { DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n")); + DumpHttpStatusCode (DEBUG_REDFISH_NETWORK, ResponseData->Response.StatusCode); Status = EFI_UNSUPPORTED; goto ON_EXIT; } @@ -426,10 +428,10 @@ ReSendRequest:; TotalReceivedSize += ResponseData->BodyLength; } - DEBUG ((DEBUG_INFO, "Total of length of Response :%d\n", TotalReceivedSize)); + DEBUG ((DEBUG_REDFISH_NETWORK, "Total of length of Response :%d\n", TotalReceivedSize)); } - DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status)); + DEBUG ((DEBUG_REDFISH_NETWORK, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status)); ON_EXIT: -- 2.39.2 From cb4820b6c148e62f9317799610b6e8dcd346c936 Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:28 +0800 Subject: [PATCH 02/16] UefiCpuPkg/PiSmmCpuDxeSmm: Fix invalid InitializeMpSyncData call REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4338 No need call InitializeMpSyncData during normal boot SMI init, because mSmmMpSyncData is NULL at that time. mSmmMpSyncData is allocated in InitializeMpServiceData, which is invoked after normal boot SMI init (SmmRelocateBases). Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Cc: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Acked-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c index 655175a2c6..2ac655d032 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -1,7 +1,7 @@ /** @file Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. -Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -371,9 +371,7 @@ SmmInitHandler ( // Check XD and BTS features on each processor on normal boot // CheckFeatureSupported (); - } - - if (mIsBsp) { + } else if (mIsBsp) { // // BSP rebase is already done above. // Initialize private data during S3 resume -- 2.39.2 From 85c6c14c4c78d4e1c657632eab1d17e5a9098d94 Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:29 +0800 Subject: [PATCH 03/16] UefiCpuPkg/PiSmmCpuDxeSmm: Replace mIsBsp by mBspApicId check This patch is to replace mIsBsp by mBspApicId check. mIsBsp becomes the local variable (IsBsp), then it can be checked dynamically in the function. Instead, we define the mBspApicId, which is to record the BSP ApicId used for compare in SmmInitHandler. With this change, SmmInitHandler can be run in parallel during SMM init. Note: This patch is the per-prepared work by refining the SmmInitHandler, then, we can do the next step to combine 2 SMIs (gcSmmInitTemplate & gcSmiHandlerTemplate) into one (gcSmiHandlerTemplate), the new SMI handler will call the SmmInitHandler in parallel to do the init. Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Cc: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Reviewed-by: Ray Ni Reviewed-by: Gerd Hoffmann --- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c index 2ac655d032..6e795d1756 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -59,7 +59,6 @@ SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate = &mSmmCpuPrivateData; // SMM Relocation variables // volatile BOOLEAN *mRebased; -volatile BOOLEAN mIsBsp; /// /// Handle for the SMM CPU Protocol @@ -85,6 +84,8 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute = { EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER]; +UINT32 mBspApicId = 0; + // // SMM stack information // @@ -343,8 +344,9 @@ SmmInitHandler ( VOID ) { - UINT32 ApicId; - UINTN Index; + UINT32 ApicId; + UINTN Index; + BOOLEAN IsBsp; // // Update SMM IDT entries' code segment and load IDT @@ -352,6 +354,8 @@ SmmInitHandler ( AsmWriteIdtr (&gcSmiIdtr); ApicId = GetApicId (); + IsBsp = (BOOLEAN)(mBspApicId == ApicId); + ASSERT (mNumberOfCpus <= mMaxNumberOfCpus); for (Index = 0; Index < mNumberOfCpus; Index++) { @@ -361,7 +365,7 @@ SmmInitHandler ( // SmmCpuFeaturesInitializeProcessor ( Index, - mIsBsp, + IsBsp, gSmmCpuPrivate->ProcessorInfo, &mCpuHotPlugData ); @@ -371,7 +375,7 @@ SmmInitHandler ( // Check XD and BTS features on each processor on normal boot // CheckFeatureSupported (); - } else if (mIsBsp) { + } else if (IsBsp) { // // BSP rebase is already done above. // Initialize private data during S3 resume @@ -407,7 +411,6 @@ SmmRelocateBases ( SMRAM_SAVE_STATE_MAP BakBuf2; SMRAM_SAVE_STATE_MAP *CpuStatePtr; UINT8 *U8Ptr; - UINT32 ApicId; UINTN Index; UINTN BspIndex; @@ -448,17 +451,16 @@ SmmRelocateBases ( // // Retrieve the local APIC ID of current processor // - ApicId = GetApicId (); + mBspApicId = GetApicId (); // // Relocate SM bases for all APs // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate // - mIsBsp = FALSE; BspIndex = (UINTN)-1; for (Index = 0; Index < mNumberOfCpus; Index++) { mRebased[Index] = FALSE; - if (ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { + if (mBspApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) { SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId); // // Wait for this AP to finish its 1st SMI @@ -477,8 +479,7 @@ SmmRelocateBases ( // Relocate BSP's SMM base // ASSERT (BspIndex != (UINTN)-1); - mIsBsp = TRUE; - SendSmiIpi (ApicId); + SendSmiIpi (mBspApicId); // // Wait for the BSP to finish its 1st SMI // -- 2.39.2 From 7b8c5a8eb42a404cad208e972f977ffacb1c8446 Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:30 +0800 Subject: [PATCH 04/16] UefiCpuPkg/SmmBaseHob.h: Add SMM Base HOB Data REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4337 The default SMBASE for the x86 processor is 0x30000. When SMI happens, processor runs the SMI handler at SMBASE+0x8000. Also, the SMM save state area is within SMBASE+0x10000. One of the SMM initialization from processor perspective is to relocate and program the new SMBASE (in TSEG range) for each processor. When the SMBASE relocation happens in a PEI module, the PEI module shall produce the SMM_BASE_HOB in HOB database which tells the PiSmmCpuDxeSmm driver (runs at a later phase) about the new SMBASE for each processor. PiSmmCpuDxeSmm driver installs the SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor Index. When the HOB doesn't exist, PiSmmCpuDxeSmm driver shall relocate and program the new SMBASE itself. This patch adds the SMM Base HOB for any PEI module to do the SmBase relocation ahead of PiSmmCpuDxeSmm driver and store the relocated SmBase address in array for each processor. Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Cc: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Acked-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Include/Guid/SmmBaseHob.h | 75 ++++++++++++++++++++++++++++ UefiCpuPkg/UefiCpuPkg.dec | 5 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 UefiCpuPkg/Include/Guid/SmmBaseHob.h diff --git a/UefiCpuPkg/Include/Guid/SmmBaseHob.h b/UefiCpuPkg/Include/Guid/SmmBaseHob.h new file mode 100644 index 0000000000..115e749348 --- /dev/null +++ b/UefiCpuPkg/Include/Guid/SmmBaseHob.h @@ -0,0 +1,75 @@ +/** @file + The Smm Base HOB is used to store the information of: + * The relocated SmBase address in array for each processor. + + The default Smbase for the x86 processor is 0x30000. When SMI happens, processor + runs the SMI handler at Smbase+0x8000. Also, the SMM save state area is within + Smbase+0x10000. Since it's the start address to store the processor save state + and code for the SMI entry point, those info are tiled within an SMRAM allocated + or reserved buffer. This tile size shall be enough to cover 3 parts: + 1. Processor SMRAM Save State Map starts at Smbase + 0xfc00 + 2. Extra processor specific context start starts at Smbase + 0xfb00 + 3. SMI entry point starts at Smbase + 0x8000. + Besides, This size should be rounded up to nearest power of 2. The Smm Base HOB + producer should be responsible for reserving enough size. + + One of the SMM initialization from processor perspective is to relocate and program + the new Smbase (in TSEG range) for each processor thread. When the Smbase relocation + happens in a PEI module, the PEI module shall produce the SMM_BASE_HOB in HOB database + which tells the PiSmmCpuDxeSmm driver (which runs at a later phase) about the new + Smbase for each processor. PiSmmCpuDxeSmm driver installs the SMI handler at the + SMM_BASE_HOB.Smbase[Index]+0x8000 for processor index. When the HOB doesn't exist, + PiSmmCpuDxeSmm driver shall relocate and program the new Smbase itself. + + Note: + 1. Smbase relocation process needs to program the vender specific hardware + interface to set Smbase, it might be in the thread scope. It's doable to + program the hardware interface using DXE MP service protocol in PiSmmCpuDxeSmm + entry point. But, considering the standalone MM environment where the CpuMm + driver runs in a isolated environment and it cannot invoke any DXE or PEI MP + service, we recommend to put the hardware interface programming in a separate + PEI module instead of in the PiSmmCpuDxeSmm driver. + + 2. There is the hard requirement that SMI Entry Size <= 0x1000, data Size <= + 0x1000 in PiSmmCpuDxeSmm. So, this require the allocated or reserved buffer in + SMRAM should be >= 0x2000. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMM_BASE_HOB_H_ +#define SMM_BASE_HOB_H_ + +#define SMM_BASE_HOB_DATA_GUID \ + { \ + 0xc2217ba7, 0x03bb, 0x4f63, {0xa6, 0x47, 0x7c, 0x25, 0xc5, 0xfc, 0x9d, 0x73} \ + } + +#pragma pack(1) +typedef struct { + /// + /// ProcessorIndex tells which processor range this specific HOB instance described. + /// If ProcessorIndex is set to 0, it indicats the HOB describes the processor from + /// 0 to NumberOfProcessors - 1. The HOB list may contains multiple this HOB + /// instances. Each HOB instances describe the information for processor from + /// ProcessorIndex to ProcessorIndex + NumberOfProcessors - 1. The instance order in + /// the HOB list is random so consumer can not assume the ProcessorIndex of first + /// instance is 0. + /// + UINT32 ProcessorIndex; + /// + /// Describes the Number of all max supported processors. + /// + UINT32 NumberOfProcessors; + /// + /// Pointer to SmBase address for each processor. + /// + UINT64 SmBase[]; +} SMM_BASE_HOB_DATA; +#pragma pack() + +extern EFI_GUID gSmmBaseHobGuid; + +#endif diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index 903ad52da9..2115aa4387 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -1,7 +1,7 @@ ## @file UefiCpuPkg.dec # This Package provides UEFI compatible CPU modules and libraries. # -# Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -78,6 +78,9 @@ ## Include/Guid/MicrocodePatchHob.h gEdkiiMicrocodePatchHobGuid = { 0xd178f11d, 0x8716, 0x418e, { 0xa1, 0x31, 0x96, 0x7d, 0x2a, 0xc4, 0x28, 0x43 }} + ## Include/Guid/SmmBaseHob.h + gSmmBaseHobGuid = { 0xc2217ba7, 0x03bb, 0x4f63, {0xa6, 0x47, 0x7c, 0x25, 0xc5, 0xfc, 0x9d, 0x73 }} + [Protocols] ## Include/Protocol/SmmCpuService.h gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }} -- 2.39.2 From ec07fd0e35d90dbcc36be300a9ceeac29c5de2ad Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:31 +0800 Subject: [PATCH 05/16] UefiCpuPkg/PiSmmCpuDxeSmm: Consume SMM Base Hob for SmBase info REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4337 Existing SMBASE Relocation is in the PiSmmCpuDxeSmm driver, which will relocate the SMBASE of each processor by setting the SMBASE field in the saved state map (at offset 7EF8h) to a new value. The RSM instruction reloads the internal SMBASE register with the value in SMBASE field when each time it exits SMM. All subsequent SMI requests will use the new SMBASE to find the starting address for the SMI handler (at SMBASE + 8000h). Due to the default SMBASE for all x86 processors is 0x30000, the APs' 1st SMI for rebase has to be executed one by one to avoid the processors over-writing each other's SMM Save State Area (see existing SmmRelocateBases() function), which means the next AP has to wait for the previous AP to finish its 1st SMI, then it can call into its 1st SMI for rebase via Smi Ipi command, thus leading the existing SMBASE Relocation has to be running in series. Besides, it needs very complex code to handle the AP exit semaphore (mRebased[Index]), which will hook return address of SMM Save State so that semaphore code can be executed immediately after AP exits SMM for SMBASE relocation (see existing SemaphoreHook() function). With SMM Base Hob support, PiSmmCpuDxeSmm does not need the RSM instruction to do the SMBASE Relocation. SMBASE Register for each processors have already been programmed and all SMBASE address have recorded in SMM Base Hob. So the same default SMBASE Address (0x30000) will not be used, thus the processors over-writing each other's SMM Save State Area will not happen in PiSmmCpuDxeSmm driver. This way makes the first SMI init can be executed in parallel and save boot time on multi-core system. Besides, Semaphore Hook code logic is also not required, which will greatly simplify the SMBASE Relocation flow. Mainly changes as below: * Assume the biggest possibility of tile size is 8k. * Combine 2 SMIs (gcSmmInitTemplate & gcSmiHandlerTemplate) into one (gcSmiHandlerTemplate), the new SMI handler needs to run to 2 paths: one to SmmCpuFeaturesInitializeProcessor(), the other to SMM Core Entry Point. * Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for first SMI init before normal SMI sources happen. * Call SmmCpuFeaturesInitializeProcessor() in parallel. Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Acked-by: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Reviewed-by: Ray Ni --- UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 31 +++- UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c | 25 ++- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 166 +++++++++++++++---- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 26 ++- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 3 +- 5 files changed, 214 insertions(+), 37 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c index fb4a44eab6..d408b3f9f7 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c @@ -1,7 +1,7 @@ /** @file Code for Processor S3 restoration -Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -824,9 +824,34 @@ SmmRestoreCpu ( } // - // Restore SMBASE for BSP and all APs + // Make sure the gSmmBaseHobGuid existence status is the same between normal and S3 boot. // - SmmRelocateBases (); + ASSERT (mSmmRelocated == (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL)); + if (mSmmRelocated != (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL)) { + DEBUG (( + DEBUG_ERROR, + "gSmmBaseHobGuid %a produced in normal boot but %a in S3 boot!", + mSmmRelocated ? "is" : "is not", + mSmmRelocated ? "is not" : "is" + )); + CpuDeadLoop (); + } + + // + // Check whether Smm Relocation is done or not. + // If not, will do the SmmBases Relocation here!!! + // + if (!mSmmRelocated) { + // + // Restore SMBASE for BSP and all APs + // + SmmRelocateBases (); + } else { + // + // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. + // + ExecuteFirstSmiInit (); + } // // Skip initialization if mAcpiCpuData is not valid diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c index a0967eb69c..baf827cf9d 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c @@ -1,7 +1,7 @@ /** @file SMM MP service implementation -Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -1723,6 +1723,10 @@ SmiRendezvous ( ASSERT (CpuIndex < mMaxNumberOfCpus); + if (mSmmRelocated) { + ASSERT (mSmmInitialized != NULL); + } + // // Save Cr2 because Page Fault exception in SMM may override its value, // when using on-demand paging for above 4G memory. @@ -1730,6 +1734,25 @@ SmiRendezvous ( Cr2 = 0; SaveCr2 (&Cr2); + if (mSmmRelocated && !mSmmInitialized[CpuIndex]) { + // + // Perform SmmInitHandler for CpuIndex + // + SmmInitHandler (); + + // + // Restore Cr2 + // + RestoreCr2 (Cr2); + + // + // Mark the first SMI init for CpuIndex has been done so as to avoid the reentry. + // + mSmmInitialized[CpuIndex] = TRUE; + + return; + } + // // Call the user register Startup function first. // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c index 6e795d1756..d2d0950f3b 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -84,6 +84,8 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute = { EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER]; +BOOLEAN mSmmRelocated = FALSE; +volatile BOOLEAN *mSmmInitialized = NULL; UINT32 mBspApicId = 0; // @@ -383,10 +385,12 @@ SmmInitHandler ( InitializeMpSyncData (); } - // - // Hook return after RSM to set SMM re-based flag - // - SemaphoreHook (Index, &mRebased[Index]); + if (!mSmmRelocated) { + // + // Hook return after RSM to set SMM re-based flag + // + SemaphoreHook (Index, &mRebased[Index]); + } return; } @@ -395,6 +399,51 @@ SmmInitHandler ( ASSERT (FALSE); } +/** + Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. + +**/ +VOID +ExecuteFirstSmiInit ( + VOID + ) +{ + UINTN Index; + + if (mSmmInitialized == NULL) { + mSmmInitialized = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * mMaxNumberOfCpus); + } + + ASSERT (mSmmInitialized != NULL); + if (mSmmInitialized == NULL) { + return; + } + + // + // Reset the mSmmInitialized to false. + // + ZeroMem ((VOID *)mSmmInitialized, sizeof (BOOLEAN) * mMaxNumberOfCpus); + + // + // Get the BSP ApicId. + // + mBspApicId = GetApicId (); + + // + // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for SMM init + // + SendSmiIpi (mBspApicId); + SendSmiIpiAllExcludingSelf (); + + // + // Wait for all processors to finish its 1st SMI + // + for (Index = 0; Index < mNumberOfCpus; Index++) { + while (!(BOOLEAN)mSmmInitialized[Index]) { + } + } +} + /** Relocate SmmBases for each processor. @@ -562,6 +611,11 @@ PiCpuSmmEntry ( UINTN FamilyId; UINTN ModelId; UINT32 Cr3; + EFI_HOB_GUID_TYPE *GuidHob; + SMM_BASE_HOB_DATA *SmmBaseHobData; + + GuidHob = NULL; + SmmBaseHobData = NULL; // // Initialize address fixup @@ -790,26 +844,54 @@ PiCpuSmmEntry ( ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET)); // - // Allocate buffer for all of the tiles. - // - // Intel(R) 64 and IA-32 Architectures Software Developer's Manual - // Volume 3C, Section 34.11 SMBASE Relocation - // For Pentium and Intel486 processors, the SMBASE values must be - // aligned on a 32-KByte boundary or the processor will enter shutdown - // state during the execution of a RSM instruction. - // - // Intel486 processors: FamilyId is 4 - // Pentium processors : FamilyId is 5 + // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found, + // means the SmBase relocation has been done. // - BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)); - if ((FamilyId == 4) || (FamilyId == 5)) { - Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB); + GuidHob = GetFirstGuidHob (&gSmmBaseHobGuid); + if (GuidHob != NULL) { + // + // Check whether the Required TileSize is enough. + // + if (TileSize > SIZE_8KB) { + DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB)); + CpuDeadLoop (); + return RETURN_BUFFER_TOO_SMALL; + } + + SmmBaseHobData = GET_GUID_HOB_DATA (GuidHob); + + // + // Assume single instance of HOB produced, expect the HOB.NumberOfProcessors equals to the mMaxNumberOfCpus. + // + ASSERT (SmmBaseHobData->NumberOfProcessors == (UINT32)mMaxNumberOfCpus && SmmBaseHobData->ProcessorIndex == 0); + mSmmRelocated = TRUE; } else { - Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB); - } + // + // When the HOB doesn't exist, allocate new SMBASE itself. + // + DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n")); + // + // Allocate buffer for all of the tiles. + // + // Intel(R) 64 and IA-32 Architectures Software Developer's Manual + // Volume 3C, Section 34.11 SMBASE Relocation + // For Pentium and Intel486 processors, the SMBASE values must be + // aligned on a 32-KByte boundary or the processor will enter shutdown + // state during the execution of a RSM instruction. + // + // Intel486 processors: FamilyId is 4 + // Pentium processors : FamilyId is 5 + // + BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)); + if ((FamilyId == 4) || (FamilyId == 5)) { + Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB); + } else { + Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB); + } - ASSERT (Buffer != NULL); - DEBUG ((DEBUG_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages))); + ASSERT (Buffer != NULL); + DEBUG ((DEBUG_INFO, "New Allcoated SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages))); + } // // Allocate buffer for pointers to array in SMM_CPU_PRIVATE_DATA. @@ -844,7 +926,8 @@ PiCpuSmmEntry ( // size for each CPU in the platform // for (Index = 0; Index < mMaxNumberOfCpus; Index++) { - mCpuHotPlugData.SmBase[Index] = (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET; + mCpuHotPlugData.SmBase[Index] = mSmmRelocated ? (UINTN)SmmBaseHobData->SmBase[Index] : (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET; + gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP); gSmmCpuPrivate->CpuSaveState[Index] = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET); gSmmCpuPrivate->Operation[Index] = SmmCpuNone; @@ -957,17 +1040,23 @@ PiCpuSmmEntry ( InitializeSmmIdt (); // - // Relocate SMM Base addresses to the ones allocated from SMRAM + // Check whether Smm Relocation is done or not. + // If not, will do the SmmBases Relocation here!!! // - mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus); - ASSERT (mRebased != NULL); - SmmRelocateBases (); + if (!mSmmRelocated) { + // + // Relocate SMM Base addresses to the ones allocated from SMRAM + // + mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus); + ASSERT (mRebased != NULL); + SmmRelocateBases (); - // - // Call hook for BSP to perform extra actions in normal mode after all - // SMM base addresses have been relocated on all CPUs - // - SmmCpuFeaturesSmmRelocationComplete (); + // + // Call hook for BSP to perform extra actions in normal mode after all + // SMM base addresses have been relocated on all CPUs + // + SmmCpuFeaturesSmmRelocationComplete (); + } DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported)); @@ -998,6 +1087,21 @@ PiCpuSmmEntry ( } } + // + // For relocated SMBASE, some MSRs & CSRs are still required to be configured in SMM Mode for SMM Initialization. + // Those MSRs & CSRs must be configured before normal SMI sources happen. + // So, here is to issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. + // + if (mSmmRelocated) { + ExecuteFirstSmiInit (); + + // + // Call hook for BSP to perform extra actions in normal mode after all + // SMM base addresses have been relocated on all CPUs + // + SmmCpuFeaturesSmmRelocationComplete (); + } + // // Fill in SMM Reserved Regions // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h index 5f0a38e400..c3731f174b 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h @@ -1,7 +1,7 @@ /** @file Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. -Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -25,6 +25,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -348,6 +349,25 @@ SmmWriteSaveState ( IN CONST VOID *Buffer ); +/** + C function for SMI handler. To change all processor's SMMBase Register. + +**/ +VOID +EFIAPI +SmmInitHandler ( + VOID + ); + +/** + Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. + +**/ +VOID +ExecuteFirstSmiInit ( + VOID + ); + /** Read a CPU Save State register on the target processor. @@ -402,6 +422,10 @@ WriteSaveStateRegister ( IN CONST VOID *Buffer ); +extern BOOLEAN mSmmRelocated; +extern volatile BOOLEAN *mSmmInitialized; +extern UINT32 mBspApicId; + extern CONST UINT8 gcSmmInitTemplate[]; extern CONST UINT16 gcSmmInitSize; X86_ASSEMBLY_PATCH_LABEL gPatchSmmCr0; diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf index b4b327f60c..9bfa8c1a76 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf @@ -4,7 +4,7 @@ # This SMM driver performs SMM initialization, deploy SMM Entry Vector, # provides CPU specific services in SMM. # -# Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
# Copyright (c) 2017, AMD Incorporated. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent @@ -114,6 +114,7 @@ gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot. gEdkiiPiSmmMemoryAttributesTableGuid ## CONSUMES ## SystemTable gEfiMemoryAttributesTableGuid ## CONSUMES ## SystemTable + gSmmBaseHobGuid ## CONSUMES [FeaturePcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug ## CONSUMES -- 2.39.2 From f6b86eec5aeb44b205d44312c99f420a96ada43f Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:32 +0800 Subject: [PATCH 06/16] UefiCpuPkg/SmmCpuFeaturesLib: Skip SMBASE configuration REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4337 This patch is to avoid configure SMBASE if SmBase relocation has been done. If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded in the SmBase array. No need to do the relocation in SmmCpuFeaturesInitializeProcessor(). Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Acked-by: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Reviewed-by: Ray Ni --- .../SmmCpuFeaturesLib/CpuFeaturesLib.h | 2 ++ .../IntelSmmCpuFeaturesLib.c | 25 ++++++++++++++++--- .../SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf | 6 ++++- .../SmmCpuFeaturesLibStm.inf | 3 ++- UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c | 3 +-- .../StandaloneMmCpuFeaturesLib.inf | 6 ++++- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h b/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h index fd3e902547..c2e4fbe96b 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h @@ -9,11 +9,13 @@ #ifndef CPU_FEATURES_LIB_H_ #define CPU_FEATURES_LIB_H_ +#include #include #include #include #include #include +#include /** Performs library initialization. diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c index d5eaaa7a99..1a2c706fa1 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c @@ -1,7 +1,7 @@ /** @file Implementation shared across all library instances. -Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -38,6 +38,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent UINT32 mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE; UINT32 mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK; +// +// Indicate SmBase for each Processors has been relocated or not. If TRUE, +// means no need to do the relocation in SmmCpuFeaturesInitializeProcessor(). +// +BOOLEAN mSmmCpuFeaturesSmmRelocated; + // // Set default value to assume MTRRs need to be configured on each SMI // @@ -144,6 +150,12 @@ CpuFeaturesLibInitialization ( // mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ()); ASSERT (mSmrrEnabled != NULL); + + // + // If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded + // in the SmBase array. + // + mSmmCpuFeaturesSmmRelocated = (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL); } /** @@ -187,10 +199,15 @@ SmmCpuFeaturesInitializeProcessor ( UINTN ModelId; // - // Configure SMBASE. + // No need to configure SMBASE if SmBase relocation has been done. // - CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET); - CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex]; + if (!mSmmCpuFeaturesSmmRelocated) { + // + // Configure SMBASE. + // + CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET); + CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex]; + } // // Intel(R) 64 and IA-32 Architectures Software Developer's Manual diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf index 9ac7dde78f..46ae2bf85e 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf @@ -1,7 +1,7 @@ ## @file # The CPU specific programming for PiSmmCpuDxeSmm module. # -# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -33,6 +33,10 @@ PcdLib MemoryAllocationLib DebugLib + HobLib + +[Guids] + gSmmBaseHobGuid ## CONSUMES [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf index 86d367e0a0..51322ff189 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf @@ -2,7 +2,7 @@ # The CPU specific programming for PiSmmCpuDxeSmm module when STM support # is included. # -# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -64,6 +64,7 @@ gMsegSmramGuid ## SOMETIMES_CONSUMES ## HOB gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gSmmBaseHobGuid ## CONSUMES [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c index 3cf162ada0..6cb1c515c0 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c @@ -1,14 +1,13 @@ /** @file SMM STM support functions - Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include -#include #include #include #include diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf index b1f60a5505..c836939d33 100644 --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf @@ -1,7 +1,7 @@ ## @file # Standalone MM CPU specific programming. # -# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -34,6 +34,10 @@ DebugLib MemoryAllocationLib PcdLib + HobLib + +[Guids] + gSmmBaseHobGuid ## CONSUMES [FixedPcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES -- 2.39.2 From a1d595fc9c049874b972a371fe6090738a176f5b Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:33 +0800 Subject: [PATCH 07/16] OvmfPkg/SmmCpuFeaturesLib: Check SmBase relocation supported or not REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4337 This patch is to check SmBase relocation supported or not. If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded in the SmBase array. ASSERT it's not supported in OVMF. Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Cc: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Reviewed-by: Gerd Hoffmann Reviewed-by: Ray Ni --- OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c | 10 +++++++++- .../Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c index 6693666d04..a1dd10c9f2 100644 --- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c +++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c @@ -1,7 +1,7 @@ /** @file The CPU specific programming for PiSmmCpuDxeSmm module. - Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -17,10 +17,12 @@ #include #include #include +#include #include #include #include #include +#include // // EFER register LMA bit @@ -43,6 +45,12 @@ SmmCpuFeaturesLibConstructor ( IN EFI_SYSTEM_TABLE *SystemTable ) { + // + // If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded + // in the SmBase array. ASSERT it's not supported in OVMF. + // + ASSERT (GetFirstGuidHob (&gSmmBaseHobGuid) == NULL); + // // No need to program SMRRs on our virtual platform. // diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf index 8a426a4c10..2697a90525 100644 --- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf +++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf @@ -1,7 +1,7 @@ ## @file # The CPU specific programming for PiSmmCpuDxeSmm module. # -# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -35,6 +35,10 @@ SafeIntLib SmmServicesTableLib UefiBootServicesTableLib + HobLib + +[Guids] + gSmmBaseHobGuid ## CONSUMES [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber -- 2.39.2 From 46f51898ff716e53921b93e8d78af0fc7d06a2f9 Mon Sep 17 00:00:00 2001 From: Rebecca Cran Date: Fri, 24 Feb 2023 08:18:01 +0800 Subject: [PATCH 08/16] MdeModulePkg: Improve formatting of DEBUG messages in UsbBusDxe Improve the formatting of DEBUG messages in UsbBusDxe by adding a hyphen to separate the EFI_STATUS code. Signed-off-by: Rebecca Cran Reviewed-by: Hao A Wu --- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c | 12 ++++++------ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c | 6 +++--- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c | 2 +- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c index 6a3ac63c3a..c25f3cc2f2 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c @@ -838,7 +838,7 @@ UsbIoPortReset ( if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n", + "UsbIoPortReset: failed to reset hub port %d@hub %d - %r\n", Dev->ParentPort, Dev->ParentAddr, Status @@ -945,7 +945,7 @@ UsbBusBuildProtocol ( ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open device path %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open device path - %r\n", Status)); FreePool (UsbBus); return Status; @@ -978,7 +978,7 @@ UsbBusBuildProtocol ( ); if (EFI_ERROR (Status) && EFI_ERROR (Status2)) { - DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC - %r\n", Status)); Status = EFI_DEVICE_ERROR; goto CLOSE_HC; @@ -1006,7 +1006,7 @@ UsbBusBuildProtocol ( ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to install bus protocol - %r\n", Status)); goto CLOSE_HC; } @@ -1054,7 +1054,7 @@ UsbBusBuildProtocol ( Status = mUsbRootHubApi.Init (RootIf); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to init root hub - %r\n", Status)); goto FREE_ROOTHUB; } @@ -1102,7 +1102,7 @@ CLOSE_HC: ); FreePool (UsbBus); - DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to start bus driver - %r\n", Status)); return Status; } diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c index a620a67074..8b078e7e49 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c @@ -761,7 +761,7 @@ UsbGetOneConfig ( if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "UsbGetOneConfig: failed to get descript length(%d) %r\n", + "UsbGetOneConfig: failed to get descript length(%d) - %r\n", Desc.TotalLength, Status )); @@ -787,7 +787,7 @@ UsbGetOneConfig ( Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, Buf, Desc.TotalLength); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbGetOneConfig: failed to get full descript - %r\n", Status)); FreePool (Buf); return NULL; @@ -891,7 +891,7 @@ UsbBuildDescTable ( Status = UsbBuildLangTable (UsbDev); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "UsbBuildDescTable: get language ID table %r\n", Status)); + DEBUG ((DEBUG_INFO, "UsbBuildDescTable: get language ID table - %r\n", Status)); } return EFI_SUCCESS; diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index aed34596f4..b3a40639f2 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -440,7 +440,7 @@ UsbSelectConfig ( if (EFI_ERROR (Status)) { DEBUG (( DEBUG_WARN, - "UsbSelectConfig: failed to connect driver %r, ignored\n", + "UsbSelectConfig: failed to connect driver - %r, ignored\n", Status )); } diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 0497a73f44..1a473d0998 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -609,7 +609,7 @@ UsbHubInit ( Status = UsbHubReadDesc (HubDev, HubDesc); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status)); + DEBUG ((DEBUG_ERROR, "UsbHubInit: failed to read HUB descriptor - %r\n", Status)); return Status; } -- 2.39.2 From 0c3f8766b00bfc8e97728f3d96b8d8c084575fa6 Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:47 +0800 Subject: [PATCH 09/16] UefiCpuPkg: Check AP_SAFE_STACK_SIZE during build time. Check if AP_SAFE_STACK_SIZE is aligned with CPU_STACK_ALIGNMENT during build time. No functional or structural changes. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/MpLib.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index f5086e497e..a73a89d2a5 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -1,7 +1,7 @@ /** @file Common header file for MP Initialize Library. - Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2020, AMD Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -311,6 +311,7 @@ typedef struct { #define AP_SAFE_STACK_SIZE 128 #define AP_RESET_STACK_SIZE AP_SAFE_STACK_SIZE +STATIC_ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0, "AP_SAFE_STACK_SIZE is not aligned with CPU_STACK_ALIGNMENT"); #pragma pack(1) -- 2.39.2 From a6f799e7fdb6389178485ddd36f472df100cebba Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:48 +0800 Subject: [PATCH 10/16] UefiCpuPkg: Split the path in RelocateApLoop into two. Add the union RELOCATE_AP_LOOP_ENTRY, split the path in RelocateApLoop into two: 1. 64-bit AMD processors with SEV-ES 2. Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 70 +++++++++++++++---------- UefiCpuPkg/Library/MpInitLib/MpLib.h | 6 +++ 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index a84e9e33ba..e9ac858f4f 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -1,7 +1,7 @@ /** @file MP initialize support functions for DXE phase. - Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -20,14 +20,14 @@ #define AP_SAFE_STACK_SIZE 128 -CPU_MP_DATA *mCpuMpData = NULL; -EFI_EVENT mCheckAllApsEvent = NULL; -EFI_EVENT mMpInitExitBootServicesEvent = NULL; -EFI_EVENT mLegacyBootEvent = NULL; -volatile BOOLEAN mStopCheckAllApsStatus = TRUE; -VOID *mReservedApLoopFunc = NULL; -UINTN mReservedTopOfApStack; -volatile UINT32 mNumberToFinish = 0; +CPU_MP_DATA *mCpuMpData = NULL; +EFI_EVENT mCheckAllApsEvent = NULL; +EFI_EVENT mMpInitExitBootServicesEvent = NULL; +EFI_EVENT mLegacyBootEvent = NULL; +volatile BOOLEAN mStopCheckAllApsStatus = TRUE; +RELOCATE_AP_LOOP_ENTRY mReservedApLoop; +UINTN mReservedTopOfApStack; +volatile UINT32 mNumberToFinish = 0; // // Begin wakeup buffer allocation below 0x88000 @@ -378,32 +378,46 @@ RelocateApLoop ( IN OUT VOID *Buffer ) { - CPU_MP_DATA *CpuMpData; - BOOLEAN MwaitSupport; - ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; - UINTN ProcessorNumber; - UINTN StackStart; + CPU_MP_DATA *CpuMpData; + BOOLEAN MwaitSupport; + UINTN ProcessorNumber; + UINTN StackStart; MpInitLibWhoAmI (&ProcessorNumber); CpuMpData = GetCpuMpData (); MwaitSupport = IsMwaitSupport (); if (CpuMpData->UseSevEsAPMethod) { + // + // 64-bit AMD processors with SEV-ES + // StackStart = CpuMpData->SevEsAPResetStackStart; + mReservedApLoop.AmdSevEntry ( + MwaitSupport, + CpuMpData->ApTargetCState, + CpuMpData->PmCodeSegment, + StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, + (UINTN)&mNumberToFinish, + CpuMpData->Pm16CodeSegment, + CpuMpData->SevEsAPBuffer, + CpuMpData->WakeupBuffer + ); } else { + // + // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES + // StackStart = mReservedTopOfApStack; + mReservedApLoop.GenericEntry ( + MwaitSupport, + CpuMpData->ApTargetCState, + CpuMpData->PmCodeSegment, + StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, + (UINTN)&mNumberToFinish, + CpuMpData->Pm16CodeSegment, + CpuMpData->SevEsAPBuffer, + CpuMpData->WakeupBuffer + ); } - AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP)(UINTN)mReservedApLoopFunc; - AsmRelocateApLoopFunc ( - MwaitSupport, - CpuMpData->ApTargetCState, - CpuMpData->PmCodeSegment, - StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, - (UINTN)&mNumberToFinish, - CpuMpData->Pm16CodeSegment, - CpuMpData->SevEsAPBuffer, - CpuMpData->WakeupBuffer - ); // // It should never reach here // @@ -547,8 +561,8 @@ InitMpGlobalData ( ); ASSERT_EFI_ERROR (Status); - mReservedApLoopFunc = (VOID *)(UINTN)Address; - ASSERT (mReservedApLoopFunc != NULL); + mReservedApLoop.Data = (VOID *)(UINTN)Address; + ASSERT (mReservedApLoop.Data != NULL); // // Make sure that the buffer memory is executable if NX protection is enabled @@ -583,7 +597,7 @@ InitMpGlobalData ( mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize; ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); CopyMem ( - mReservedApLoopFunc, + mReservedApLoop.Data, CpuMpData->AddressMap.RelocateApLoopFuncAddress, CpuMpData->AddressMap.RelocateApLoopFuncSize ); diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index a73a89d2a5..81a95733fc 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -402,6 +402,12 @@ AsmExchangeRole ( IN CPU_EXCHANGE_ROLE_INFO *OthersInfo ); +typedef union { + VOID *Data; + ASM_RELOCATE_AP_LOOP AmdSevEntry; // 64-bit AMD Sev processors + ASM_RELOCATE_AP_LOOP GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors +} RELOCATE_AP_LOOP_ENTRY; + /** Get the pointer to CPU MP Data structure. -- 2.39.2 From e9782e69070c3a876f6bc1af966603cc1fc90320 Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:49 +0800 Subject: [PATCH 11/16] UefiCpuPkg: Allocate contiguous memory for stacks and APs loop. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 40 +++++++++++-------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index e9ac858f4f..224215878c 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -480,11 +480,12 @@ InitMpGlobalData ( { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Address; - UINTN ApSafeBufferSize; UINTN Index; EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; UINTN StackBase; CPU_INFO_IN_HOB *CpuInfoInHob; + UINTN StackPages; + UINTN FuncPages; SaveCpuMpData (CpuMpData); @@ -547,16 +548,23 @@ InitMpGlobalData ( // Allocating it in advance since memory services are not available in // Exit Boot Services callback function. // - ApSafeBufferSize = EFI_PAGES_TO_SIZE ( - EFI_SIZE_TO_PAGES ( - CpuMpData->AddressMap.RelocateApLoopFuncSize - ) - ); + // +------------+ (TopOfApStack) + // | Stack * N | + // +------------+ (stack base, 4k aligned) + // | Padding | + // +------------+ + // | Ap Loop | + // +------------+ ((low address, 4k-aligned) + // + + StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE); + FuncPages = EFI_SIZE_TO_PAGES (CpuMpData->AddressMap.RelocateApLoopFuncSize); + Address = BASE_4GB - 1; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiReservedMemoryType, - EFI_SIZE_TO_PAGES (ApSafeBufferSize), + StackPages + FuncPages, &Address ); ASSERT_EFI_ERROR (Status); @@ -575,26 +583,12 @@ InitMpGlobalData ( if (!EFI_ERROR (Status)) { gDS->SetMemorySpaceAttributes ( Address, - ApSafeBufferSize, + EFI_PAGES_TO_SIZE (FuncPages), MemDesc.Attributes & (~EFI_MEMORY_XP) ); } - ApSafeBufferSize = EFI_PAGES_TO_SIZE ( - EFI_SIZE_TO_PAGES ( - CpuMpData->CpuCount * AP_SAFE_STACK_SIZE - ) - ); - Address = BASE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - EFI_SIZE_TO_PAGES (ApSafeBufferSize), - &Address - ); - ASSERT_EFI_ERROR (Status); - - mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize; + mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages); ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); CopyMem ( mReservedApLoop.Data, -- 2.39.2 From c6e655743ffb4d510d153c8179f6740841f70010 Mon Sep 17 00:00:00 2001 From: Yuanhao Xie Date: Wed, 1 Mar 2023 14:09:50 +0800 Subject: [PATCH 12/16] OvmfPkg: Add CpuPageTableLib required by MpInitLib. Add CpuPageTableLib required by MpInitLib in OvmfPkg. Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Jordan Justen Cc: Gerd Hoffmann Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- OvmfPkg/AmdSev/AmdSevX64.dsc | 3 ++- OvmfPkg/CloudHv/CloudHvX64.dsc | 3 ++- OvmfPkg/IntelTdx/IntelTdxX64.dsc | 4 +++- OvmfPkg/Microvm/MicrovmX64.dsc | 3 ++- OvmfPkg/OvmfPkgIa32X64.dsc | 3 ++- OvmfPkg/OvmfPkgX64.dsc | 4 +++- OvmfPkg/OvmfXen.dsc | 3 ++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index 1cebd6b4bc..f0c4dc2310 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -3,7 +3,7 @@ # virtual machine remote attestation and secret injection # # Copyright (c) 2020 James Bottomley, IBM Corporation. -# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# # SPDX-License-Identifier: BSD-2-Clause-Patent @@ -353,6 +353,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc index fda7d2b9e5..327f53ff3c 100644 --- a/OvmfPkg/CloudHv/CloudHvX64.dsc +++ b/OvmfPkg/CloudHv/CloudHvX64.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation. # @@ -404,6 +404,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc index 95b9594ddc..d093660283 100644 --- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc +++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation. # @@ -320,6 +320,7 @@ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxDxeLib.inf PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf @@ -590,6 +591,7 @@ # Directly use DxeMpInitLib. It depends on DxeMpInitLibMpDepLib which # checks the Protocol of gEfiMpInitLibMpDepProtocolGuid. # + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NULL|OvmfPkg/Library/MpInitLibDepLib/DxeMpInitLibMpDepLib.inf } diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc index 0d65d21e65..76fc548650 100644 --- a/OvmfPkg/Microvm/MicrovmX64.dsc +++ b/OvmfPkg/Microvm/MicrovmX64.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation. # @@ -403,6 +403,7 @@ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf PciExpressLib|OvmfPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 6b539814bd..51db692b10 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation. # @@ -414,6 +414,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index e3c64456df..04d50704c7 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation. # @@ -435,6 +435,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf @@ -826,6 +827,7 @@ # Directly use DxeMpInitLib. It depends on DxeMpInitLibMpDepLib which # checks the Protocol of gEfiMpInitLibMpDepProtocolGuid. # + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NULL|OvmfPkg/Library/MpInitLibDepLib/DxeMpInitLibMpDepLib.inf } diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index c328987e84..f1f02d969f 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -1,7 +1,7 @@ ## @file # EFI/Framework Open Virtual Machine Firmware (OVMF) platform # -# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright (c) 2019, Citrix Systems, Inc. # Copyright (c) Microsoft Corporation. @@ -339,6 +339,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf NestedInterruptTplLib|OvmfPkg/Library/NestedInterruptTplLib/NestedInterruptTplLib.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf -- 2.39.2 From 6bc74286e7f57d6c7bd29a7b5e4eb8026c5a8012 Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:51 +0800 Subject: [PATCH 13/16] UefiPayloadPkg: Add CpuPageTableLib required by MpInitLib. Add CpuPageTableLib required by MpInitLib in UefiPayloadPkg. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiPayloadPkg/UefiPayloadPkg.dsc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 2dbd875f37..8cbbbe9a05 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -3,7 +3,7 @@ # # Provides drivers and definitions to create uefi payload for bootloaders. # -# Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2014 - 2023, Intel Corporation. All rights reserved.
# Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -340,6 +340,7 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf !if $(PERFORMANCE_MEASUREMENT_ENABLE) PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf -- 2.39.2 From facf52aeb8accb312acfd34b60266d4ea866afbb Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:52 +0800 Subject: [PATCH 14/16] UefiCpuPkg: Put APs in 64 bit mode before handoff to OS. Add the 'AsmRelocateApLoopStartGeneric' for X64 processors except 64-bit AMD processors with SEV-ES. Remove the unused arguments of AsmRelocateApLoopStartGeneric, updated the stack offset. Create PageTable for the allocated reserved memory. Only keep 4GB limitation of memory allocation for the case APs still need to be transferred to 32-bit mode before OS. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 6 +- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 63 +++++++++----- .../Library/MpInitLib/Ia32/CreatePageTable.c | 23 ++++++ .../Library/MpInitLib/Ia32/MpFuncs.nasm | 26 +++--- UefiCpuPkg/Library/MpInitLib/MpEqu.inc | 22 ++--- UefiCpuPkg/Library/MpInitLib/MpLib.h | 43 +++++++++- .../Library/MpInitLib/X64/CreatePageTable.c | 82 +++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 57 ++++++++++++- 8 files changed, 273 insertions(+), 49 deletions(-) create mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index cd07de3a3c..4285dd06b4 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -1,7 +1,7 @@ ## @file # MP Initialize Library instance for DXE driver. # -# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -24,10 +24,12 @@ [Sources.IA32] Ia32/AmdSev.c Ia32/MpFuncs.nasm + Ia32/CreatePageTable.c [Sources.X64] X64/AmdSev.c X64/MpFuncs.nasm + X64/CreatePageTable.c [Sources.common] AmdSev.c @@ -56,6 +58,8 @@ PcdLib CcExitLib MicrocodeLib +[LibraryClasses.X64] + CpuPageTableLib [Protocols] gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 224215878c..d292277d10 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -28,6 +28,7 @@ volatile BOOLEAN mStopCheckAllApsStatus = TRUE; RELOCATE_AP_LOOP_ENTRY mReservedApLoop; UINTN mReservedTopOfApStack; volatile UINT32 mNumberToFinish = 0; +UINTN mApPageTable; // // Begin wakeup buffer allocation below 0x88000 @@ -409,12 +410,9 @@ RelocateApLoop ( mReservedApLoop.GenericEntry ( MwaitSupport, CpuMpData->ApTargetCState, - CpuMpData->PmCodeSegment, StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, (UINTN)&mNumberToFinish, - CpuMpData->Pm16CodeSegment, - CpuMpData->SevEsAPBuffer, - CpuMpData->WakeupBuffer + mApPageTable ); } @@ -484,6 +482,9 @@ InitMpGlobalData ( EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; UINTN StackBase; CPU_INFO_IN_HOB *CpuInfoInHob; + MP_ASSEMBLY_ADDRESS_MAP *AddressMap; + UINT8 *ApLoopFunc; + UINTN ApLoopFuncSize; UINTN StackPages; UINTN FuncPages; @@ -540,6 +541,23 @@ InitMpGlobalData ( } } + AddressMap = &CpuMpData->AddressMap; + if (CpuMpData->UseSevEsAPMethod) { + // + // 64-bit AMD processors with SEV-ES + // + Address = BASE_4GB - 1; + ApLoopFunc = AddressMap->RelocateApLoopFuncAddress; + ApLoopFuncSize = AddressMap->RelocateApLoopFuncSize; + } else { + // + // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES + // + Address = MAX_ADDRESS; + ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric; + ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric; + } + // // Avoid APs access invalid buffer data which allocated by BootServices, // so we will allocate reserved data for AP loop code. We also need to @@ -558,19 +576,15 @@ InitMpGlobalData ( // StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE); - FuncPages = EFI_SIZE_TO_PAGES (CpuMpData->AddressMap.RelocateApLoopFuncSize); - - Address = BASE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - StackPages + FuncPages, - &Address - ); - ASSERT_EFI_ERROR (Status); + FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize); - mReservedApLoop.Data = (VOID *)(UINTN)Address; - ASSERT (mReservedApLoop.Data != NULL); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + StackPages + FuncPages, + &Address + ); + ASSERT_EFI_ERROR (Status); // // Make sure that the buffer memory is executable if NX protection is enabled @@ -590,11 +604,18 @@ InitMpGlobalData ( mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages); ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); - CopyMem ( - mReservedApLoop.Data, - CpuMpData->AddressMap.RelocateApLoopFuncAddress, - CpuMpData->AddressMap.RelocateApLoopFuncSize - ); + mReservedApLoop.Data = (VOID *)(UINTN)Address; + ASSERT (mReservedApLoop.Data != NULL); + CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize); + if (!CpuMpData->UseSevEsAPMethod) { + // + // processors without SEV-ES + // + mApPageTable = CreatePageTable ( + (UINTN)Address, + EFI_PAGES_TO_SIZE (StackPages+FuncPages) + ); + } Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c new file mode 100644 index 0000000000..bec9b247c0 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c @@ -0,0 +1,23 @@ +/** @file + Function to create page talbe. + Only create page table for x64, and leave the CreatePageTable empty for Ia32. + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +/** + Only create page table for x64, and leave the CreatePageTable empty for Ia32. + @param[in] LinearAddress The start of the linear address range. + @param[in] Length The length of the linear address range. + @return The page table to be created. +**/ +UINTN +CreatePageTable ( + IN UINTN Address, + IN UINTN Length + ) +{ + return 0; +} diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm index bfcdbd31c1..59db4081d6 100644 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.
+; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent ; ; Module Name: @@ -219,24 +219,24 @@ SwitchToRealProcEnd: RendezvousFunnelProcEnd: ;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); +; AsmRelocateApLoopGeneric (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); ; ; The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are ; specific to SEV-ES support and are not applicable on IA32. ;------------------------------------------------------------------------------------- -AsmRelocateApLoopStart: +AsmRelocateApLoopGenericStart: mov eax, esp - mov esp, [eax + 16] ; TopOfApStack + mov esp, [eax + 12] ; TopOfApStack push dword [eax] ; push return address for stack trace push ebp mov ebp, esp mov ebx, [eax + 8] ; ApTargetCState mov ecx, [eax + 4] ; MwaitSupport - mov eax, [eax + 20] ; CountTofinish + mov eax, [eax + 16] ; CountTofinish lock dec dword [eax] ; (*CountTofinish)-- cmp cl, 1 ; Check mwait-monitor support - jnz HltLoop -MwaitLoop: + jnz HltLoopGeneric +MwaitLoopGeneric: cli mov eax, esp xor ecx, ecx @@ -245,12 +245,12 @@ MwaitLoop: mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] shl eax, 4 mwait - jmp MwaitLoop -HltLoop: + jmp MwaitLoopGeneric +HltLoopGeneric: cli hlt - jmp HltLoop -AsmRelocateApLoopEnd: + jmp HltLoopGeneric +AsmRelocateApLoopGenericEnd: ;------------------------------------------------------------------------------------- ; AsmGetAddressMap (&AddressMap); @@ -264,8 +264,8 @@ ASM_PFX(AsmGetAddressMap): mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], RendezvousFunnelProcStart mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart - mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], AsmRelocateApLoopStart - mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart + mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], AsmRelocateApLoopGenericStart + mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], 0 diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc index ebadcc6fb3..09c1817426 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc +++ b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.
+; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent ; ; Module Name: @@ -21,15 +21,17 @@ CPU_SWITCH_STATE_LOADED equ 2 ; Equivalent NASM structure of MP_ASSEMBLY_ADDRESS_MAP ; struc MP_ASSEMBLY_ADDRESS_MAP - .RendezvousFunnelAddress CTYPE_UINTN 1 - .ModeEntryOffset CTYPE_UINTN 1 - .RendezvousFunnelSize CTYPE_UINTN 1 - .RelocateApLoopFuncAddress CTYPE_UINTN 1 - .RelocateApLoopFuncSize CTYPE_UINTN 1 - .ModeTransitionOffset CTYPE_UINTN 1 - .SwitchToRealNoNxOffset CTYPE_UINTN 1 - .SwitchToRealPM16ModeOffset CTYPE_UINTN 1 - .SwitchToRealPM16ModeSize CTYPE_UINTN 1 + .RendezvousFunnelAddress CTYPE_UINTN 1 + .ModeEntryOffset CTYPE_UINTN 1 + .RendezvousFunnelSize CTYPE_UINTN 1 + .RelocateApLoopFuncAddressGeneric CTYPE_UINTN 1 + .RelocateApLoopFuncSizeGeneric CTYPE_UINTN 1 + .RelocateApLoopFuncAddress CTYPE_UINTN 1 + .RelocateApLoopFuncSize CTYPE_UINTN 1 + .ModeTransitionOffset CTYPE_UINTN 1 + .SwitchToRealNoNxOffset CTYPE_UINTN 1 + .SwitchToRealPM16ModeOffset CTYPE_UINTN 1 + .SwitchToRealPM16ModeSize CTYPE_UINTN 1 endstruc ; diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 81a95733fc..e137545fc6 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -177,6 +177,8 @@ typedef struct { UINT8 *RendezvousFunnelAddress; UINTN ModeEntryOffset; UINTN RendezvousFunnelSize; + UINT8 *RelocateApLoopFuncAddressGeneric; + UINTN RelocateApLoopFuncSizeGeneric; UINT8 *RelocateApLoopFuncAddress; UINTN RelocateApLoopFuncSize; UINTN ModeTransitionOffset; @@ -361,6 +363,29 @@ extern EFI_GUID mCpuInitMpLibHobGuid; @param[in] ApTargetCState Target C-State value. @param[in] PmCodeSegment Protected mode code segment value. **/ +typedef + VOID +(EFIAPI *ASM_RELOCATE_AP_LOOP_GENERIC)( + IN BOOLEAN MwaitSupport, + IN UINTN ApTargetCState, + IN UINTN TopOfApStack, + IN UINTN NumberToFinish, + IN UINTN Cr3 + ); + +/** + Assembly code to place AP into safe loop mode for Amd processors + with Sev enabled. + Place AP into targeted C-State if MONITOR is supported, otherwise + place AP into hlt state. + Place AP in protected mode if the current is long mode. Due to AP maybe + wakeup by some hardware event. It could avoid accessing page table that + may not available during booting to OS. + @param[in] MwaitSupport TRUE indicates MONITOR is supported. + FALSE indicates MONITOR is not supported. + @param[in] ApTargetCState Target C-State value. + @param[in] PmCodeSegment Protected mode code segment value. +**/ typedef VOID (EFIAPI *ASM_RELOCATE_AP_LOOP)( @@ -403,9 +428,9 @@ AsmExchangeRole ( ); typedef union { - VOID *Data; - ASM_RELOCATE_AP_LOOP AmdSevEntry; // 64-bit AMD Sev processors - ASM_RELOCATE_AP_LOOP GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors + VOID *Data; + ASM_RELOCATE_AP_LOOP AmdSevEntry; // 64-bit AMD Sev processors + ASM_RELOCATE_AP_LOOP_GENERIC GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors } RELOCATE_AP_LOOP_ENTRY; /** @@ -471,6 +496,18 @@ GetSevEsAPMemory ( VOID ); +/** + Create 1:1 mapping page table in reserved memory to map the specified address range. + @param[in] LinearAddress The start of the linear address range. + @param[in] Length The length of the linear address range. + @return The page table to be created. +**/ +UINTN +CreatePageTable ( + IN UINTN Address, + IN UINTN Length + ); + /** This function will be called by BSP to wakeup AP. diff --git a/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c new file mode 100644 index 0000000000..7cf91ed9c4 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c @@ -0,0 +1,82 @@ +/** @file + Function to create page talbe. + Only create page table for x64, and leave the CreatePageTable empty for Ia32. + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include +#include +#include +#include +#include +#include + +/** + Create 1:1 mapping page table in reserved memory to map the specified address range. + @param[in] LinearAddress The start of the linear address range. + @param[in] Length The length of the linear address range. + @return The page table to be created. +**/ +UINTN +CreatePageTable ( + IN UINTN Address, + IN UINTN Length + ) +{ + EFI_STATUS Status; + VOID *PageTableBuffer; + UINTN PageTableBufferSize; + UINTN PageTable; + PAGING_MODE PagingMode; + IA32_CR4 Cr4; + + IA32_MAP_ATTRIBUTE MapAttribute; + IA32_MAP_ATTRIBUTE MapMask; + + MapAttribute.Uint64 = Address; + MapAttribute.Bits.Present = 1; + MapAttribute.Bits.ReadWrite = 1; + + MapMask.Bits.PageTableBaseAddress = 1; + MapMask.Bits.Present = 1; + MapMask.Bits.ReadWrite = 1; + + PageTable = 0; + PageTableBufferSize = 0; + + Cr4.UintN = AsmReadCr4 (); + + if (Cr4.Bits.LA57 == 1) { + PagingMode = Paging5Level; + } else { + PagingMode = Paging4Level; + } + + Status = PageTableMap ( + &PageTable, + PagingMode, + NULL, + &PageTableBufferSize, + Address, + Length, + &MapAttribute, + &MapMask + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + DEBUG ((DEBUG_INFO, "AP Page Table Buffer Size = %x\n", PageTableBufferSize)); + + PageTableBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); + ASSERT (PageTableBuffer != NULL); + Status = PageTableMap ( + &PageTable, + PagingMode, + PageTableBuffer, + &PageTableBufferSize, + Address, + Length, + &MapAttribute, + &MapMask + ); + ASSERT_EFI_ERROR (Status); + return PageTable; +} diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index 5d71995bf8..c0d7355c6b 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.
+; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent ; ; Module Name: @@ -447,6 +447,58 @@ DoHlt: BITS 64 AsmRelocateApLoopEnd: +;------------------------------------------------------------------------------------- +; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3); +; This function is called during the finalizaiton of Mp initialization before booting +; to OS, and aim to put Aps either in Mwait or HLT. +;------------------------------------------------------------------------------------- +; +----------------+ +; | Cr3 | rsp+40 +; +----------------+ +; | CountTofinish | r9 +; +----------------+ +; | TopOfApStack | r8 +; +----------------+ +; | ApTargetCState | rdx +; +----------------+ +; | MwaitSupport | rcx +; +----------------+ +; | the return | +; +----------------+ low address + +AsmRelocateApLoopGenericStart: + mov rax, r9 ; CountTofinish + lock dec dword [rax] ; (*CountTofinish)-- + + mov rax, [rsp + 40] ; Cr3 + ; Do not push on old stack, since old stack is not mapped + ; in the page table pointed by cr3 + mov cr3, rax + mov rsp, r8 ; TopOfApStack + +MwaitCheckGeneric: + cmp cl, 1 ; Check mwait-monitor support + jnz HltLoopGeneric + mov rbx, rdx ; Save C-State to ebx + +MwaitLoopGeneric: + cli + mov rax, rsp ; Set Monitor Address + xor ecx, ecx ; ecx = 0 + xor edx, edx ; edx = 0 + monitor + mov rax, rbx ; Mwait Cx, Target C-State per eax[7:4] + shl eax, 4 + mwait + jmp MwaitLoopGeneric + +HltLoopGeneric: + cli + hlt + jmp HltLoopGeneric + +AsmRelocateApLoopGenericEnd: + ;------------------------------------------------------------------------------------- ; AsmGetAddressMap (&AddressMap); ;------------------------------------------------------------------------------------- @@ -456,6 +508,9 @@ ASM_PFX(AsmGetAddressMap): mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], rax mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart +lea rax, [AsmRelocateApLoopGenericStart] + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], rax + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart lea rax, [AsmRelocateApLoopStart] mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart -- 2.39.2 From 0d1ad06c27e36bef6d89a7cbdfda39b5c36fdfbe Mon Sep 17 00:00:00 2001 From: Yuanhao Xie Date: Wed, 1 Mar 2023 14:09:53 +0800 Subject: [PATCH 15/16] UefiCpuPkg: Rename AsmRelocateApLoopStart. Rename AsmRelocateApLoopStart to AsmRelocateApLoopStartAmdSev Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 4 +- UefiCpuPkg/Library/MpInitLib/MpEqu.inc | 4 +- UefiCpuPkg/Library/MpInitLib/MpLib.h | 8 ++-- UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 40 +++++++++---------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index d292277d10..330676b700 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -547,8 +547,8 @@ InitMpGlobalData ( // 64-bit AMD processors with SEV-ES // Address = BASE_4GB - 1; - ApLoopFunc = AddressMap->RelocateApLoopFuncAddress; - ApLoopFuncSize = AddressMap->RelocateApLoopFuncSize; + ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev; + ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev; } else { // // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc index 09c1817426..72af196513 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc +++ b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc @@ -26,8 +26,8 @@ struc MP_ASSEMBLY_ADDRESS_MAP .RendezvousFunnelSize CTYPE_UINTN 1 .RelocateApLoopFuncAddressGeneric CTYPE_UINTN 1 .RelocateApLoopFuncSizeGeneric CTYPE_UINTN 1 - .RelocateApLoopFuncAddress CTYPE_UINTN 1 - .RelocateApLoopFuncSize CTYPE_UINTN 1 + .RelocateApLoopFuncAddressAmdSev CTYPE_UINTN 1 + .RelocateApLoopFuncSizeAmdSev CTYPE_UINTN 1 .ModeTransitionOffset CTYPE_UINTN 1 .SwitchToRealNoNxOffset CTYPE_UINTN 1 .SwitchToRealPM16ModeOffset CTYPE_UINTN 1 diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index e137545fc6..6f235dcf6d 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -179,8 +179,8 @@ typedef struct { UINTN RendezvousFunnelSize; UINT8 *RelocateApLoopFuncAddressGeneric; UINTN RelocateApLoopFuncSizeGeneric; - UINT8 *RelocateApLoopFuncAddress; - UINTN RelocateApLoopFuncSize; + UINT8 *RelocateApLoopFuncAddressAmdSev; + UINTN RelocateApLoopFuncSizeAmdSev; UINTN ModeTransitionOffset; UINTN SwitchToRealNoNxOffset; UINTN SwitchToRealPM16ModeOffset; @@ -388,7 +388,7 @@ typedef **/ typedef VOID -(EFIAPI *ASM_RELOCATE_AP_LOOP)( +(EFIAPI *ASM_RELOCATE_AP_LOOP_AMDSEV)( IN BOOLEAN MwaitSupport, IN UINTN ApTargetCState, IN UINTN PmCodeSegment, @@ -429,7 +429,7 @@ AsmExchangeRole ( typedef union { VOID *Data; - ASM_RELOCATE_AP_LOOP AmdSevEntry; // 64-bit AMD Sev processors + ASM_RELOCATE_AP_LOOP_AMDSEV AmdSevEntry; // 64-bit AMD Sev processors ASM_RELOCATE_AP_LOOP_GENERIC GenericEntry; // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or AMD non-Sev processors } RELOCATE_AP_LOOP_ENTRY; diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index c0d7355c6b..1a64d5681f 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -277,14 +277,14 @@ CProcedureInvoke: %include "AmdSev.nasm" RendezvousFunnelProcEnd: - ;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); +; AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); ;------------------------------------------------------------------------------------- -AsmRelocateApLoopStart: + +AsmRelocateApLoopAmdSevStart: BITS 64 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable - je NoSevEs + je NoSevEsAmdSev ; ; Perform some SEV-ES related setup before leaving 64-bit mode @@ -329,7 +329,7 @@ BITS 64 pop rdx pop rcx -NoSevEs: +NoSevEsAmdSev: cli ; Disable interrupt before switching to 32-bit mode mov rax, [rsp + 40] ; CountTofinish lock dec dword [rax] ; (*CountTofinish)-- @@ -345,7 +345,7 @@ NoSevEs: push rcx ; Save MwaitSupport push rdx ; Save ApTargetCState - lea rax, [PmEntry] ; rax <- The start address of transition code + lea rax, [PmEntryAmdSev] ; rax <- The start address of transition code push r8 push rax @@ -365,10 +365,10 @@ NoSevEs: ; ; Far return into 32-bit mode ; - retfq +o64 retf BITS 32 -PmEntry: +PmEntryAmdSev: mov eax, cr0 btr eax, 31 ; Clear CR0.PG mov cr0, eax ; Disable paging and caches @@ -386,11 +386,11 @@ PmEntry: pop ecx, add esp, 4 -MwaitCheck: +MwaitCheckAmdSev: cmp cl, 1 ; Check mwait-monitor support - jnz HltLoop + jnz HltLoopAmdSev mov ebx, edx ; Save C-State to ebx -MwaitLoop: +MwaitLoopAmdSev: cli mov eax, esp ; Set Monitor Address xor ecx, ecx ; ecx = 0 @@ -399,9 +399,9 @@ MwaitLoop: mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] shl eax, 4 mwait - jmp MwaitLoop + jmp MwaitLoopAmdSev -HltLoop: +HltLoopAmdSev: pop edx ; PM16CodeSegment add esp, 4 pop ebx ; WakeupBuffer @@ -409,7 +409,7 @@ HltLoop: pop eax ; SevEsAPJumpTable add esp, 4 cmp eax, 0 ; Check for SEV-ES - je DoHlt + je DoHltAmdSev cli ; @@ -439,13 +439,13 @@ BITS 32 retf -DoHlt: +DoHltAmdSev: cli hlt - jmp DoHlt + jmp DoHltAmdSev BITS 64 -AsmRelocateApLoopEnd: +AsmRelocateApLoopAmdSevEnd: ;------------------------------------------------------------------------------------- ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3); @@ -511,9 +511,9 @@ ASM_PFX(AsmGetAddressMap): lea rax, [AsmRelocateApLoopGenericStart] mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], rax mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart - lea rax, [AsmRelocateApLoopStart] - mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax - mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart + lea rax, [AsmRelocateApLoopAmdSevStart] + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressAmdSev], rax + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeAmdSev], AsmRelocateApLoopAmdSevEnd - AsmRelocateApLoopAmdSevStart mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], PM16Mode - RendezvousFunnelProcStart -- 2.39.2 From c7c25997595aa34ce0a7a21ca2e1fc5b0f9b38a6 Mon Sep 17 00:00:00 2001 From: "Xie, Yuanhao" Date: Wed, 1 Mar 2023 14:09:54 +0800 Subject: [PATCH 16/16] UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Acked-by: Gerd Hoffmann Tested-by: Gerd Hoffmann Reviewed-by: Ray Ni --- UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm | 170 ++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 169 ----------------- 2 files changed, 170 insertions(+), 169 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm index 7c2469f9c5..2efa3cb104 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm @@ -346,3 +346,173 @@ PM16Mode: iret SwitchToRealProcEnd: + +;------------------------------------------------------------------------------------- +; AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); +;------------------------------------------------------------------------------------- + +AsmRelocateApLoopAmdSevStart: +BITS 64 + cmp qword [rsp + 56], 0 ; SevEsAPJumpTable + je NoSevEsAmdSev + + ; + ; Perform some SEV-ES related setup before leaving 64-bit mode + ; + push rcx + push rdx + + ; + ; Get the RDX reset value using CPUID + ; + mov rax, 1 + cpuid + mov rsi, rax ; Save off the reset value for RDX + + ; + ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call + ; - Must be done while in 64-bit long mode so that writes to + ; the GHCB memory will be unencrypted. + ; - No NAE events can be generated once this is set otherwise + ; the AP_RESET_HOLD SW_EXITCODE will be overwritten. + ; + mov rcx, 0xc0010130 + rdmsr ; Retrieve current GHCB address + shl rdx, 32 + or rdx, rax + + mov rdi, rdx + xor rax, rax + mov rcx, 0x800 + shr rcx, 3 + rep stosq ; Clear the GHCB + + mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD + mov [rdx + 0x390], rax + mov rax, 114 ; Set SwExitCode valid bit + bts [rdx + 0x3f0], rax + inc rax ; Set SwExitInfo1 valid bit + bts [rdx + 0x3f0], rax + inc rax ; Set SwExitInfo2 valid bit + bts [rdx + 0x3f0], rax + + pop rdx + pop rcx + +NoSevEsAmdSev: + cli ; Disable interrupt before switching to 32-bit mode + mov rax, [rsp + 40] ; CountTofinish + lock dec dword [rax] ; (*CountTofinish)-- + + mov r10, [rsp + 48] ; Pm16CodeSegment + mov rax, [rsp + 56] ; SevEsAPJumpTable + mov rbx, [rsp + 64] ; WakeupBuffer + mov rsp, r9 ; TopOfApStack + + push rax ; Save SevEsAPJumpTable + push rbx ; Save WakeupBuffer + push r10 ; Save Pm16CodeSegment + push rcx ; Save MwaitSupport + push rdx ; Save ApTargetCState + + lea rax, [PmEntryAmdSev] ; rax <- The start address of transition code + + push r8 + push rax + + ; + ; Clear R8 - R15, for reset, before going into 32-bit mode + ; + xor r8, r8 + xor r9, r9 + xor r10, r10 + xor r11, r11 + xor r12, r12 + xor r13, r13 + xor r14, r14 + xor r15, r15 + + ; + ; Far return into 32-bit mode + ; +o64 retf + +BITS 32 +PmEntryAmdSev: + mov eax, cr0 + btr eax, 31 ; Clear CR0.PG + mov cr0, eax ; Disable paging and caches + + mov ecx, 0xc0000080 + rdmsr + and ah, ~ 1 ; Clear LME + wrmsr + mov eax, cr4 + and al, ~ (1 << 5) ; Clear PAE + mov cr4, eax + + pop edx + add esp, 4 + pop ecx, + add esp, 4 + +MwaitCheckAmdSev: + cmp cl, 1 ; Check mwait-monitor support + jnz HltLoopAmdSev + mov ebx, edx ; Save C-State to ebx +MwaitLoopAmdSev: + cli + mov eax, esp ; Set Monitor Address + xor ecx, ecx ; ecx = 0 + xor edx, edx ; edx = 0 + monitor + mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] + shl eax, 4 + mwait + jmp MwaitLoopAmdSev + +HltLoopAmdSev: + pop edx ; PM16CodeSegment + add esp, 4 + pop ebx ; WakeupBuffer + add esp, 4 + pop eax ; SevEsAPJumpTable + add esp, 4 + cmp eax, 0 ; Check for SEV-ES + je DoHltAmdSev + + cli + ; + ; SEV-ES is enabled, use VMGEXIT (GHCB information already + ; set by caller) + ; +BITS 64 + rep vmmcall +BITS 32 + + ; + ; Back from VMGEXIT AP_HLT_LOOP + ; Push the FLAGS/CS/IP values to use + ; + push word 0x0002 ; EFLAGS + xor ecx, ecx + mov cx, [eax + 2] ; CS + push cx + mov cx, [eax] ; IP + push cx + push word 0x0000 ; For alignment, will be discarded + + push edx + push ebx + + mov edx, esi ; Restore RDX reset value + + retf + +DoHltAmdSev: + cli + hlt + jmp DoHltAmdSev + +BITS 64 +AsmRelocateApLoopAmdSevEnd: diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index 1a64d5681f..9ebe31795b 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -277,175 +277,6 @@ CProcedureInvoke: %include "AmdSev.nasm" RendezvousFunnelProcEnd: -;------------------------------------------------------------------------------------- -; AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); -;------------------------------------------------------------------------------------- - -AsmRelocateApLoopAmdSevStart: -BITS 64 - cmp qword [rsp + 56], 0 ; SevEsAPJumpTable - je NoSevEsAmdSev - - ; - ; Perform some SEV-ES related setup before leaving 64-bit mode - ; - push rcx - push rdx - - ; - ; Get the RDX reset value using CPUID - ; - mov rax, 1 - cpuid - mov rsi, rax ; Save off the reset value for RDX - - ; - ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call - ; - Must be done while in 64-bit long mode so that writes to - ; the GHCB memory will be unencrypted. - ; - No NAE events can be generated once this is set otherwise - ; the AP_RESET_HOLD SW_EXITCODE will be overwritten. - ; - mov rcx, 0xc0010130 - rdmsr ; Retrieve current GHCB address - shl rdx, 32 - or rdx, rax - - mov rdi, rdx - xor rax, rax - mov rcx, 0x800 - shr rcx, 3 - rep stosq ; Clear the GHCB - - mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD - mov [rdx + 0x390], rax - mov rax, 114 ; Set SwExitCode valid bit - bts [rdx + 0x3f0], rax - inc rax ; Set SwExitInfo1 valid bit - bts [rdx + 0x3f0], rax - inc rax ; Set SwExitInfo2 valid bit - bts [rdx + 0x3f0], rax - - pop rdx - pop rcx - -NoSevEsAmdSev: - cli ; Disable interrupt before switching to 32-bit mode - mov rax, [rsp + 40] ; CountTofinish - lock dec dword [rax] ; (*CountTofinish)-- - - mov r10, [rsp + 48] ; Pm16CodeSegment - mov rax, [rsp + 56] ; SevEsAPJumpTable - mov rbx, [rsp + 64] ; WakeupBuffer - mov rsp, r9 ; TopOfApStack - - push rax ; Save SevEsAPJumpTable - push rbx ; Save WakeupBuffer - push r10 ; Save Pm16CodeSegment - push rcx ; Save MwaitSupport - push rdx ; Save ApTargetCState - - lea rax, [PmEntryAmdSev] ; rax <- The start address of transition code - - push r8 - push rax - - ; - ; Clear R8 - R15, for reset, before going into 32-bit mode - ; - xor r8, r8 - xor r9, r9 - xor r10, r10 - xor r11, r11 - xor r12, r12 - xor r13, r13 - xor r14, r14 - xor r15, r15 - - ; - ; Far return into 32-bit mode - ; -o64 retf - -BITS 32 -PmEntryAmdSev: - mov eax, cr0 - btr eax, 31 ; Clear CR0.PG - mov cr0, eax ; Disable paging and caches - - mov ecx, 0xc0000080 - rdmsr - and ah, ~ 1 ; Clear LME - wrmsr - mov eax, cr4 - and al, ~ (1 << 5) ; Clear PAE - mov cr4, eax - - pop edx - add esp, 4 - pop ecx, - add esp, 4 - -MwaitCheckAmdSev: - cmp cl, 1 ; Check mwait-monitor support - jnz HltLoopAmdSev - mov ebx, edx ; Save C-State to ebx -MwaitLoopAmdSev: - cli - mov eax, esp ; Set Monitor Address - xor ecx, ecx ; ecx = 0 - xor edx, edx ; edx = 0 - monitor - mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] - shl eax, 4 - mwait - jmp MwaitLoopAmdSev - -HltLoopAmdSev: - pop edx ; PM16CodeSegment - add esp, 4 - pop ebx ; WakeupBuffer - add esp, 4 - pop eax ; SevEsAPJumpTable - add esp, 4 - cmp eax, 0 ; Check for SEV-ES - je DoHltAmdSev - - cli - ; - ; SEV-ES is enabled, use VMGEXIT (GHCB information already - ; set by caller) - ; -BITS 64 - rep vmmcall -BITS 32 - - ; - ; Back from VMGEXIT AP_HLT_LOOP - ; Push the FLAGS/CS/IP values to use - ; - push word 0x0002 ; EFLAGS - xor ecx, ecx - mov cx, [eax + 2] ; CS - push cx - mov cx, [eax] ; IP - push cx - push word 0x0000 ; For alignment, will be discarded - - push edx - push ebx - - mov edx, esi ; Restore RDX reset value - - retf - -DoHltAmdSev: - cli - hlt - jmp DoHltAmdSev - -BITS 64 -AsmRelocateApLoopAmdSevEnd: ;------------------------------------------------------------------------------------- ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3); -- 2.39.2