Skip to content

Commit

Permalink
OvmfPkg/SmmRelocationLib: Add library instance for OVMF
Browse files Browse the repository at this point in the history
There are below 2 differences between AMD & OVMF according
existing implementation:
1.The mode of the CPU check is different between the AMD & OVMF.
OVMF:
CpuSaveState->x86.SMMRevId & 0Xffff

AMD:
 LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA

2.Existing SmBase configuration is different between the
AMD & OVMF.
OVMF:
 if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
   CpuSaveState->x86.SMBASE = mSmBaseForAllCpus[CpuIndex];
 } else {
   CpuSaveState->x64.SMBASE = mSmBaseForAllCpus[CpuIndex];
 }

AMD:
 AmdCpuState->x64.SMBASE = mSmBaseForAllCpus[CpuIndex];

This patch provides the SmmRelocationLib library instance
for OVMF to handle the logic difference, and it won't change
the existing implementation code logic.

Cc: Ray Ni <ray.ni@intel.com>
Cc: Zeng Star <star.zeng@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Tested-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
  • Loading branch information
jiaxinwu authored and mergify[bot] committed May 8, 2024
1 parent 47f2122 commit 3dfd643
Show file tree
Hide file tree
Showing 14 changed files with 1,299 additions and 0 deletions.
1 change: 1 addition & 0 deletions OvmfPkg/AmdSev/AmdSevX64.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
!include MdePkg/MdeLibs.dsc.inc

[LibraryClasses]
SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
Expand Down
1 change: 1 addition & 0 deletions OvmfPkg/CloudHv/CloudHvX64.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
!include MdePkg/MdeLibs.dsc.inc

[LibraryClasses]
SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
Expand Down
39 changes: 39 additions & 0 deletions OvmfPkg/Library/SmmRelocationLib/Ia32/Semaphore.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/** @file
Semaphore mechanism to indicate to the BSP that an AP has exited SMM
after SMBASE relocation.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "InternalSmmRelocationLib.h"

UINTN mSmmRelocationOriginalAddress;
volatile BOOLEAN *mRebasedFlag;

/**
Hook return address of SMM Save State so that semaphore code
can be executed immediately after AP exits SMM to indicate to
the BSP that an AP has exited SMM after SMBASE relocation.
@param[in] RebasedFlag A pointer to a flag that is set to TRUE
immediately after AP exits SMM.
**/
VOID
SemaphoreHook (
IN volatile BOOLEAN *RebasedFlag
)
{
SMRAM_SAVE_STATE_MAP *CpuState;

mRebasedFlag = RebasedFlag;

CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
mSmmRelocationOriginalAddress = (UINTN)HookReturnFromSmm (
CpuState,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete
);
}
151 changes: 151 additions & 0 deletions OvmfPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
;
; SmmInit.nasm
;
; Abstract:
;
; Functions for relocating SMBASE's for all processors
;
;-------------------------------------------------------------------------------

%include "StuffRsbNasm.inc"

extern ASM_PFX(SmmInitHandler)
extern ASM_PFX(mRebasedFlag)
extern ASM_PFX(mSmmRelocationOriginalAddress)

global ASM_PFX(gPatchSmmInitCr3)
global ASM_PFX(gPatchSmmInitCr4)
global ASM_PFX(gPatchSmmInitCr0)
global ASM_PFX(gPatchSmmInitStack)
global ASM_PFX(gcSmmInitGdtr)
global ASM_PFX(gcSmmInitSize)
global ASM_PFX(gcSmmInitTemplate)

%define PROTECT_MODE_CS 0x8
%define PROTECT_MODE_DS 0x20

SECTION .data

NullSeg: DQ 0 ; reserved by architecture
CodeSeg32:
DW -1 ; LimitLow
DW 0 ; BaseLow
DB 0 ; BaseMid
DB 0x9b
DB 0xcf ; LimitHigh
DB 0 ; BaseHigh
ProtModeCodeSeg32:
DW -1 ; LimitLow
DW 0 ; BaseLow
DB 0 ; BaseMid
DB 0x9b
DB 0xcf ; LimitHigh
DB 0 ; BaseHigh
ProtModeSsSeg32:
DW -1 ; LimitLow
DW 0 ; BaseLow
DB 0 ; BaseMid
DB 0x93
DB 0xcf ; LimitHigh
DB 0 ; BaseHigh
DataSeg32:
DW -1 ; LimitLow
DW 0 ; BaseLow
DB 0 ; BaseMid
DB 0x93
DB 0xcf ; LimitHigh
DB 0 ; BaseHigh
CodeSeg16:
DW -1
DW 0
DB 0
DB 0x9b
DB 0x8f
DB 0
DataSeg16:
DW -1
DW 0
DB 0
DB 0x93
DB 0x8f
DB 0
CodeSeg64:
DW -1 ; LimitLow
DW 0 ; BaseLow
DB 0 ; BaseMid
DB 0x9b
DB 0xaf ; LimitHigh
DB 0 ; BaseHigh
GDT_SIZE equ $ - NullSeg

ASM_PFX(gcSmmInitGdtr):
DW GDT_SIZE - 1
DD NullSeg


SECTION .text

global ASM_PFX(SmmStartup)

BITS 16
ASM_PFX(SmmStartup):
mov eax, 0x80000001 ; read capability
cpuid
mov ebx, edx ; rdmsr will change edx. keep it in ebx.
and ebx, BIT20 ; extract NX capability bit
shr ebx, 9 ; shift bit to IA32_EFER.NXE[BIT11] position
mov eax, strict dword 0 ; source operand will be patched
ASM_PFX(gPatchSmmInitCr3):
mov cr3, eax
o32 lgdt [cs:ebp + (ASM_PFX(gcSmmInitGdtr) - ASM_PFX(SmmStartup))]
mov eax, strict dword 0 ; source operand will be patched
ASM_PFX(gPatchSmmInitCr4):
mov cr4, eax
mov ecx, 0xc0000080 ; IA32_EFER MSR
rdmsr
or eax, ebx ; set NXE bit if NX is available
wrmsr
mov eax, strict dword 0 ; source operand will be patched
ASM_PFX(gPatchSmmInitCr0):
mov di, PROTECT_MODE_DS
mov cr0, eax
jmp PROTECT_MODE_CS : dword @32bit

BITS 32
@32bit:
mov ds, edi
mov es, edi
mov fs, edi
mov gs, edi
mov ss, edi
mov esp, strict dword 0 ; source operand will be patched
ASM_PFX(gPatchSmmInitStack):
call ASM_PFX(SmmInitHandler)
StuffRsb32
rsm

BITS 16
ASM_PFX(gcSmmInitTemplate):
mov ebp, ASM_PFX(SmmStartup)
sub ebp, 0x30000
jmp ebp

ASM_PFX(gcSmmInitSize): DW $ - ASM_PFX(gcSmmInitTemplate)

BITS 32
global ASM_PFX(SmmRelocationSemaphoreComplete)
ASM_PFX(SmmRelocationSemaphoreComplete):
push eax
mov eax, [ASM_PFX(mRebasedFlag)]
mov byte [eax], 1
pop eax
jmp [ASM_PFX(mSmmRelocationOriginalAddress)]

global ASM_PFX(SmmInitFixupAddress)
ASM_PFX(SmmInitFixupAddress):
ret
127 changes: 127 additions & 0 deletions OvmfPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/** @file
SMM Relocation Lib for each processor.
This Lib produces 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.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef INTERNAL_SMM_RELOCATION_LIB_H_
#define INTERNAL_SMM_RELOCATION_LIB_H_

#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/LocalApicLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/SmmRelocationLib.h>
#include <Guid/SmramMemoryReserve.h>
#include <Guid/SmmBaseHob.h>
#include <Register/Intel/Cpuid.h>
#include <Register/Intel/SmramSaveStateMap.h>
#include <Protocol/MmCpu.h>

extern IA32_DESCRIPTOR gcSmmInitGdtr;
extern CONST UINT16 gcSmmInitSize;
extern CONST UINT8 gcSmmInitTemplate[];

X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr0;
X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr3;
X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr4;
X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitStack;

//
// The size 0x20 must be bigger than
// the size of template code of SmmInit. Currently,
// the size of SmmInit requires the 0x16 Bytes buffer
// at least.
//
#define BACK_BUF_SIZE 0x20

#define CR4_CET_ENABLE BIT23

//
// EFER register LMA bit
//
#define LMA BIT10

/**
This function configures the SmBase on the currently executing CPU.
@param[in] SmBase The SmBase on the currently executing CPU.
**/
VOID
EFIAPI
ConfigureSmBase (
IN UINT64 SmBase
);

/**
Semaphore operation for all processor relocate SMMBase.
**/
VOID
EFIAPI
SmmRelocationSemaphoreComplete (
VOID
);

/**
Hook the code executed immediately after an RSM instruction on the currently
executing CPU. The mode of code executed immediately after RSM must be
detected, and the appropriate hook must be selected. Always clear the auto
HALT restart flag if it is set.
@param[in,out] CpuState Pointer to SMRAM Save State Map for the
currently executing CPU.
@param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
32-bit mode from 64-bit SMM.
@param[in] NewInstructionPointer Instruction pointer to use if resuming to
same mode as SMM.
@retval The value of the original instruction pointer before it was hooked.
**/
UINT64
EFIAPI
HookReturnFromSmm (
IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
IN UINT64 NewInstructionPointer32,
IN UINT64 NewInstructionPointer
);

/**
Hook return address of SMM Save State so that semaphore code
can be executed immediately after AP exits SMM to indicate to
the BSP that an AP has exited SMM after SMBASE relocation.
@param[in] RebasedFlag A pointer to a flag that is set to TRUE
immediately after AP exits SMM.
**/
VOID
SemaphoreHook (
IN volatile BOOLEAN *RebasedFlag
);

/**
This function fixes up the address of the global variable or function
referred in SmmInit assembly files to be the absolute address.
**/
VOID
EFIAPI
SmmInitFixupAddress (
);

#endif
Loading

0 comments on commit 3dfd643

Please sign in to comment.