From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.18315.1677175578044889092 for ; Thu, 23 Feb 2023 10:06:21 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=E5nFmKvr; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: yuanhao.xie@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1677175581; x=1708711581; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BaQMZUPvtGRLZx+vKGlJQaXxFpq1fXT6QMNYnhC1Vww=; b=E5nFmKvrjVmCsLmontU8fT8UiBfQTO34e4lYrmnFdo9GsMhKfkze2uY3 Y5HZ4QyYTNPRuYzipLDoGqhXc+GA2oi8RMK7+M2hE/2hGr3iFeiKze5h5 C0jdqkQ3v9yO7NkxkoOuSnBgvMdWUpXFQ8zprexubpqQ85phxn+LPHQL7 OxxAjEMP8vRNzQE3Chjc3bj9TkOMdUEZ74DXMi3edhrBTlYOSBoDlhfs7 ky3BRAsZalZU7Vn46Z642Zu6ERTm1pOi4XqZGh3JXZ4erM9vI87FhLXG5 iuH9rINuOhcgvabPw2h9sgWr9KN+CZWcHI/yb/q2TyRAecLT7foKSuO+B w==; X-IronPort-AV: E=McAfee;i="6500,9779,10630"; a="333288079" X-IronPort-AV: E=Sophos;i="5.97,322,1669104000"; d="scan'208";a="333288079" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2023 10:06:00 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10630"; a="918106859" X-IronPort-AV: E=Sophos;i="5.97,322,1669104000"; d="scan'208";a="918106859" Received: from shwdeopenlab705.ccr.corp.intel.com ([10.239.182.166]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2023 10:05:58 -0800 From: "Yuanhao Xie" To: devel@edk2.groups.io Cc: Guo Dong , Ray Ni , Sean Rhodes , James Lu , Gua Guo Subject: [Patch V3 2/6] UefiCpuPkg: Duplicate AsmRelocateApLoopAmd. Date: Fri, 24 Feb 2023 02:05:31 +0800 Message-Id: <20230223180535.10383-3-yuanhao.xie@intel.com> X-Mailer: git-send-email 2.36.1.windows.1 In-Reply-To: <20230223180535.10383-1-yuanhao.xie@intel.com> References: <20230223180535.10383-1-yuanhao.xie@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Duplicate AsmRelocateApLoopAmd for non-SEV-ES enabled processors. Cc: Guo Dong Cc: Ray Ni Cc: Sean Rhodes Cc: James Lu Cc: Gua Guo Signed-off-by: Yuanhao Xie Test-by: Yuanhao Xie --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 68 ++++++++++++++++++++++++++++++++++++++++++++------------------------ UefiCpuPkg/Library/MpInitLib/MpEqu.inc | 22 ++++++++++++---------- UefiCpuPkg/Library/MpInitLib/MpLib.h | 31 +++++++++++++++++++++++++++++-- UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm | 33 +++++++++++++++++---------------- UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 273 insertions(+), 52 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index a84e9e33ba..dd935a79d3 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 **/ @@ -378,32 +378,44 @@ 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; + ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; + ASM_RELOCATE_AP_LOOP_AMDSEV AsmRelocateApLoopFuncAmdSev; + UINTN ProcessorNumber; + UINTN StackStart; MpInitLibWhoAmI (&ProcessorNumber); CpuMpData = GetCpuMpData (); MwaitSupport = IsMwaitSupport (); if (CpuMpData->UseSevEsAPMethod) { - StackStart = CpuMpData->SevEsAPResetStackStart; + StackStart = CpuMpData->SevEsAPResetStackStart; + AsmRelocateApLoopFuncAmdSev = (ASM_RELOCATE_AP_LOOP)(UINTN)mReservedApLoopFunc; + AsmRelocateApLoopFuncAmdSev ( + MwaitSupport, + CpuMpData->ApTargetCState, + CpuMpData->PmCodeSegment, + StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, + (UINTN)&mNumberToFinish, + CpuMpData->Pm16CodeSegment, + CpuMpData->SevEsAPBuffer, + CpuMpData->WakeupBuffer + ); } else { - StackStart = mReservedTopOfApStack; + StackStart = mReservedTopOfApStack; + 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 + ); } - 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 // @@ -582,11 +594,19 @@ InitMpGlobalData ( mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize; ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); - CopyMem ( - mReservedApLoopFunc, - CpuMpData->AddressMap.RelocateApLoopFuncAddress, - CpuMpData->AddressMap.RelocateApLoopFuncSize - ); + if (CpuMpData->UseSevEsAPMethod) { + CopyMem ( + mReservedApLoopFunc, + CpuMpData->AddressMap.RelocateApLoopFuncAddressAmdSev, + CpuMpData->AddressMap.RelocateApLoopFuncSizeAmdSev + ); + } else { + CopyMem ( + mReservedApLoopFunc, + CpuMpData->AddressMap.RelocateApLoopFuncAddress, + CpuMpData->AddressMap.RelocateApLoopFuncSize + ); + } Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc index ebadcc6fb3..6730f2f411 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 + .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 + .SwitchToRealPM16ModeSize CTYPE_UINTN 1 endstruc ; diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index f5086e497e..5011533302 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 @@ -179,6 +179,8 @@ typedef struct { UINTN RendezvousFunnelSize; UINT8 *RelocateApLoopFuncAddress; UINTN RelocateApLoopFuncSize; + UINT8 *RelocateApLoopFuncAddressAmdSev; + UINTN RelocateApLoopFuncSizeAmdSev; UINTN ModeTransitionOffset; UINTN SwitchToRealNoNxOffset; UINTN SwitchToRealPM16ModeOffset; @@ -311,7 +313,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) typedef struct { @@ -373,6 +375,31 @@ typedef IN UINTN WakeupBuffer ); +/** + 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_AMDSEV)( + IN BOOLEAN MwaitSupport, + IN UINTN ApTargetCState, + IN UINTN PmCodeSegment, + IN UINTN TopOfApStack, + IN UINTN NumberToFinish, + IN UINTN Pm16CodeSegment, + IN UINTN SevEsAPJumpTable, + IN UINTN WakeupBuffer + ); + /** Assembly code to get starting address and size of the rendezvous entry for APs. Information for fixing a jump instruction in the code is also returned. diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm index c1e8a045a4..6b48913306 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm @@ -347,12 +347,13 @@ PM16Mode: SwitchToRealProcEnd: ;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); +; AsmRelocateApLoopAmdSev (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); ;------------------------------------------------------------------------------------- -AsmRelocateApLoopStart: + +AsmRelocateApLoopStartAmdSev: BITS 64 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable - je NoSevEs + je NoSevEsAmdSev ; ; Perform some SEV-ES related setup before leaving 64-bit mode @@ -397,7 +398,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)-- @@ -413,7 +414,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 @@ -433,10 +434,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 @@ -454,11 +455,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 @@ -467,9 +468,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 @@ -477,7 +478,7 @@ HltLoop: pop eax ; SevEsAPJumpTable add esp, 4 cmp eax, 0 ; Check for SEV-ES - je DoHlt + je DoHltAmdSev cli ; @@ -507,10 +508,10 @@ BITS 32 retf -DoHlt: +DoHltAmdSev: cli hlt - jmp DoHlt + jmp DoHltAmdSev BITS 64 -AsmRelocateApLoopEnd: +AsmRelocateApLoopEndAmdSev: diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index eb42bbff96..d36f8ba06d 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -278,6 +278,174 @@ CProcedureInvoke: RendezvousFunnelProcEnd: +;------------------------------------------------------------------------------------- +; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); +;------------------------------------------------------------------------------------- +AsmRelocateApLoopStart: +BITS 64 + cmp qword [rsp + 56], 0 ; SevEsAPJumpTable + je NoSevEs + + ; + ; 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 + +NoSevEs: + 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, [PmEntry] ; 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 + ; + retfq + +BITS 32 +PmEntry: + 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 + +MwaitCheck: + cmp cl, 1 ; Check mwait-monitor support + jnz HltLoop + mov ebx, edx ; Save C-State to ebx +MwaitLoop: + 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 MwaitLoop + +HltLoop: + 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 DoHlt + + 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 + +DoHlt: + cli + hlt + jmp DoHlt + +BITS 64 +AsmRelocateApLoopEnd: ;------------------------------------------------------------------------------------- ; AsmGetAddressMap (&AddressMap); @@ -291,6 +459,9 @@ ASM_PFX(AsmGetAddressMap): lea rax, [AsmRelocateApLoopStart] mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart + lea rax, [AsmRelocateApLoopStartAmdSev] + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressAmdSev], rax + mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeAmdSev], AsmRelocateApLoopEndAmdSev - AsmRelocateApLoopStartAmdSev 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.36.1.windows.1