Skip to content

Commit

Permalink
UefiCpuPkg: Add support for testing the SMM page protections
Browse files Browse the repository at this point in the history
Adds instrumentation to the PageTbl and SmiPFHandler code to
allow reset (instead of halts) on page faults.

This enables automated testing of fault detection and handling.

Co-authored-by: Michael Kubacki <[email protected]>
Signed-off-by: Michael Kubacki <[email protected]>
  • Loading branch information
Bret Barkelew and makubacki committed Jun 20, 2024
1 parent a248cf8 commit 15492c1
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 18 deletions.
38 changes: 38 additions & 0 deletions UefiCpuPkg/Include/Protocol/SmmExceptionTestProtocol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/** @file -- SmmExceptionTestProtocol.h
A simple protocol to enable SMM exception handling being placed in test mode.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef SMM_EXCEPTION_TEST_PROTOCOL_H_
#define SMM_EXCEPTION_TEST_PROTOCOL_H_

// B76383A1-0E70-4A3F-86B4-C6134C8E5723
#define SMM_EXCEPTION_TEST_PROTOCOL_GUID \
{ \
0xb76383a1, 0x0e70, 0x4a3f, { 0x86, 0xb4, 0xc6, 0x13, 0x4c, 0x8e, 0x57, 0x23 } \
}

extern EFI_GUID gSmmExceptionTestProtocolGuid;

/**
Enable exception handling test mode.
NOTE: This should only work on debug builds, otherwise return EFI_UNSUPPORTED.
@retval EFI_SUCCESS Test mode enabled.
@retval EFI_UNSUPPORTED Test mode could not be enabled.
**/
typedef
EFI_STATUS
(EFIAPI *SMM_ENABLE_EXCEPTION_TEST_MODE)(
VOID
);

typedef struct _SMM_EXCEPTION_TEST_PROTOCOL {
SMM_ENABLE_EXCEPTION_TEST_MODE EnableTestMode;
} SMM_EXCEPTION_TEST_PROTOCOL;

#endif // SMM_EXCEPTION_TEST_PROTOCOL_H_
81 changes: 81 additions & 0 deletions UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
Expand Down Expand Up @@ -126,6 +127,39 @@ SPIN_LOCK *mConfigSmmCodeAccessCheckLock = NULL;
//
EFI_SMRAM_DESCRIPTOR *mSmmCpuSmramRanges;
UINTN mSmmCpuSmramRangeCount;
//
// MU_CHANGE [BEGIN] - Add flag to enable "test mode" for the SMM protections.
// NOTE: "Test mode" will only be enabled in DEBUG builds.
// Flag to indicate exception handling should be in test mode.
// This will cause exceptions to reset the system and/or log
// additional telemetry.
//

/**
Enable exception handling test mode.
NOTE: This should only work on debug builds, otherwise return EFI_UNSUPPORTED.
@retval EFI_SUCCESS Test mode enabled.
@retval EFI_UNSUPPORTED Test mode could not be enabled.
**/
EFI_STATUS
EFIAPI
EnableSmmExceptionTestMode (
VOID
);

//
// Protocol for other drivers to enable test mode.
//
SMM_EXCEPTION_TEST_PROTOCOL mSmmExceptionTestProtocol = {
EnableSmmExceptionTestMode
};
EFI_HANDLE mSmmExceptionTestProtocolHandle = NULL;

BOOLEAN mSmmRebootOnException = TRUE;
// MU_CHANGE [END]

UINT8 mPhysicalAddressBits;

Expand Down Expand Up @@ -874,6 +908,8 @@ PiCpuSmmEntry (
EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT
);

mSmmRebootOnException = PcdGetBool (PcdSmmExceptionRebootInsteadOfHaltDefault); // MS_CHANGE

//
// Find out SMRR Base and SMRR Size
//
Expand Down Expand Up @@ -1299,6 +1335,20 @@ PiCpuSmmEntry (
);
ASSERT_EFI_ERROR (Status);

// MU_CHANGE [BEGIN] - Add flag to enable "test mode" for the SMM protections.
// NOTE: "Test mode" will only be enabled in DEBUG builds.
if (FeaturePcdGet (PcdSmmExceptionTestModeSupport)) {
Status = gSmst->SmmInstallProtocolInterface (
&mSmmExceptionTestProtocolHandle,
&gSmmExceptionTestProtocolGuid,
EFI_NATIVE_INTERFACE,
&mSmmExceptionTestProtocol
);
ASSERT_EFI_ERROR (Status);
}

// MU_CHANGE [END]

//
// Install the SMM Memory Attribute Protocol into SMM protocol database
//
Expand Down Expand Up @@ -1745,3 +1795,34 @@ PerformPreTasks (
{
RestoreSmmConfigurationInS3 ();
}

// MU_CHANGE [BEGIN] - Add flag to enable "test mode" for the SMM protections.
// NOTE: "Test mode" will only be enabled in DEBUG builds.

/**
Enable exception handling test mode.
NOTE: This should only work on debug builds, otherwise return EFI_UNSUPPORTED.
@retval EFI_SUCCESS Test mode enabled.
@retval EFI_UNSUPPORTED Test mode could not be enabled.
**/
EFI_STATUS
EFIAPI
EnableSmmExceptionTestMode (
VOID
)
{
EFI_STATUS Status = EFI_UNSUPPORTED;

if (FeaturePcdGet (PcdSmmExceptionTestModeSupport)) {
DEBUG ((DEBUG_INFO, "%a - Test mode enabled!\n", __func__));
mSmmRebootOnException = TRUE;
Status = EFI_SUCCESS;
}

return Status;
}

// MU_CHANGE [END]
10 changes: 10 additions & 0 deletions UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/SmmCpuService.h>
#include <Protocol/SmmMemoryAttribute.h>
#include <Protocol/MmMp.h>
#include <Protocol/SmmExceptionTestProtocol.h> // MU_CHANGE - Add support for testing SMM page protections

#include <Guid/AcpiS3Context.h>
#include <Guid/MemoryAttributesTable.h>
Expand Down Expand Up @@ -192,6 +193,13 @@ typedef struct {

#define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL

// MU_CHANGE [BEGIN]
typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;
#define ARRIVAL_EXCEPTION_BLOCKED 0x1
#define ARRIVAL_EXCEPTION_DELAYED 0x2
#define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4
// MU_CHANGE [END]

//
// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.
//
Expand Down Expand Up @@ -296,6 +304,8 @@ EnableCet (
VOID
);

extern BOOLEAN mSmmRebootOnException; // MU_CHANGE

//
// SMM CPU Protocol function prototypes.
//
Expand Down
7 changes: 6 additions & 1 deletion UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# This SMM driver performs SMM initialization, deploy SMM Entry Vector,
# provides CPU specific services in SMM.
#
# Copyright (c) Microsoft Corporation.
# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
Expand Down Expand Up @@ -97,6 +98,7 @@
SmmCpuFeaturesLib
PeCoffGetEntryPointLib
PerformanceLib
HwResetSystemLib ## MU_CHANGE - Use HwResetSystemLib
CpuPageTableLib
MmSaveStateLib
SmmCpuSyncLib
Expand All @@ -105,6 +107,7 @@
gEfiSmmAccess2ProtocolGuid ## CONSUMES
gEfiSmmConfigurationProtocolGuid ## PRODUCES
gEfiSmmCpuProtocolGuid ## PRODUCES
gSmmExceptionTestProtocolGuid ## PRODUCES ## MS_CHANGE
gEfiSmmReadyToLockProtocolGuid ## NOTIFY
gEfiSmmCpuServiceProtocolGuid ## PRODUCES
gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES
Expand All @@ -129,7 +132,8 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdSmmApPerfLogEnable ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdSmmExceptionTestModeSupport
gUefiCpuPkgTokenSpaceGuid.PcdSmmApPerfLogEnable

[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES
Expand All @@ -147,6 +151,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdSmmExceptionRebootInsteadOfHaltDefault ## CONSUMES ## MS_CHANGE

[FixedPcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmMpTokenCountPerChunk ## CONSUMES
Expand Down
52 changes: 42 additions & 10 deletions UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/** @file
Page Fault (#PF) handler for X64 processors
Copyright (c) Microsoft Corporation.
Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Library/ResetSystemLib.h> // MU_CHANGE - Allow system to reset instead of halt in test mode.

#include "PiSmmCpuDxeSmm.h"

#define PAGE_TABLE_PAGES 8
Expand Down Expand Up @@ -878,8 +881,11 @@ SmiPFHandler (
if (mCpuSmmRestrictedMemoryAccess && (PFAddress >= LShiftU64 (1, (mPhysicalAddressBits - 1)))) {
DumpCpuContext (InterruptType, SystemContext);
DEBUG ((DEBUG_ERROR, "Do not support address 0x%lx by processor!\n", PFAddress));
CpuDeadLoop ();
goto Exit;
// MU_CHANGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto HaltOrReboot;
// CpuDeadLoop ();
// goto Exit;
// MU_CHANGE [END] - Allow system to reset instead of halt in test mode.
}

//
Expand Down Expand Up @@ -923,8 +929,11 @@ SmiPFHandler (
}
}

CpuDeadLoop ();
goto Exit;
// MU_CHANGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto HaltOrReboot;
// CpuDeadLoop ();
// goto Exit;
// MU_CHANGE [END] - Allow system to reset instead of halt in test mode.
}

//
Expand All @@ -939,8 +948,11 @@ SmiPFHandler (
DEBUG_CODE (
DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp);
);
CpuDeadLoop ();
goto Exit;
// MU_CHANGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto HaltOrReboot;
// CpuDeadLoop ();
// goto Exit;
// MU_CHANGE [END] - Allow system to reset instead of halt in test mode.
}

//
Expand All @@ -960,8 +972,11 @@ SmiPFHandler (
goto Exit;
}

CpuDeadLoop ();
goto Exit;
// MU_CHANGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto HaltOrReboot;
// CpuDeadLoop ();
// goto Exit;
// MU_CHANGE [END] - Allow system to reset instead of halt in test mode.
}

if (mCpuSmmRestrictedMemoryAccess && IsSmmCommBufferForbiddenAddress (PFAddress)) {
Expand All @@ -970,8 +985,11 @@ SmiPFHandler (
DEBUG_CODE (
DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);
);
CpuDeadLoop ();
goto Exit;
// MU_CHANGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto HaltOrReboot;
// CpuDeadLoop ();
// goto Exit;
// MU_CHANGE [END] - Allow system to reset instead of halt in test mode.
}
}

Expand All @@ -984,8 +1002,22 @@ SmiPFHandler (
SmiDefaultPFHandler ();
}

// MU_CHNAGE [BEGIN] - Allow system to reset instead of halt in test mode.
goto Exit;

HaltOrReboot:
if (mSmmRebootOnException) {
DEBUG ((DEBUG_ERROR, "%a - Reboot here in test mode.\n", __func__));
ResetWarm ();
CpuDeadLoop ();
} else {
CpuDeadLoop ();
}

Exit:
ReleaseSpinLock (mPFLock);
return;
// MU_CHNAGE [END] - Allow system to reset instead of halt in test mode.
}

/**
Expand Down
19 changes: 12 additions & 7 deletions UefiCpuPkg/UefiCpuPkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,10 @@

## Include/Protocol/SmMonitorInit.h
gEfiSmMonitorInitProtocolGuid = { 0x228f344d, 0xb3de, 0x43bb, { 0xa4, 0xd7, 0xea, 0x20, 0xb, 0x1b, 0x14, 0x82 }}

[Protocols.RISCV64]
#
# Protocols defined for RISC-V systems
# MU_CHANGE - Add support for testing SMM protections
#
## Include/Protocol/RiscVBootProtocol.h
gRiscVEfiBootProtocolGuid = { 0xccd15fec, 0x6f73, 0x4eec, { 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf }}
## Include/Protocol/SmmExceptionTestProtocol.h
gSmmExceptionTestProtocolGuid = { 0xb76383a1, 0x0e70, 0x4a3f, { 0x86, 0xb4, 0xc6, 0x13, 0x4c, 0x8e, 0x57, 0x23 }}

#
# [Error.gUefiCpuPkgTokenSpaceGuid]
Expand Down Expand Up @@ -194,7 +191,6 @@
# FALSE - SMM Feature Control MSR will not be locked.<BR>
# @Prompt Lock SMM Feature Control MSR.
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B

## Indicates if SMRR will be enabled.<BR><BR>
# TRUE - SMRR will be enabled.<BR>
# FALSE - SMRR will not be enabled.<BR>
Expand All @@ -206,6 +202,11 @@
# FALSE - SmmFeatureControl will not be enabled.<BR>
# @Prompt Support SmmFeatureControl.
gUefiCpuPkgTokenSpaceGuid.PcdSmmFeatureControlEnable|TRUE|BOOLEAN|0x32132110
## MS_CHANGE
## If TRUE, Install the protocol to communicate to the Smm Exception
# handler so automated testing can be performed.
#
gUefiCpuPkgTokenSpaceGuid.PcdSmmExceptionTestModeSupport|FALSE|BOOLEAN|0x00000021

## Indicates if SMM perf logging in APs will be enabled.<BR><BR>
# TRUE - SMM perf logging in APs will be enabled.<BR>
Expand Down Expand Up @@ -236,6 +237,10 @@
## Size of teh area of memory where the SEV-ES work area block lives.
# @Prompt Configure the SEV-ES work area base
gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize|0x0|UINT32|0x30002006
## MS_CHANGE
## If TRUE, the default Cpu Exception Handler in SMM will reboot
# This handler state can be changed by using the Exception Test Protocol
gUefiCpuPkgTokenSpaceGuid.PcdSmmExceptionRebootInsteadOfHaltDefault|TRUE|BOOLEAN|0x00000020

## Determining APs' first-time wakeup by SIPI or INIT-SIPI-SIPI.
# Following a power-up or RESET of an MP system, The APs complete a
Expand Down
5 changes: 5 additions & 0 deletions UefiCpuPkg/UefiCpuPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf
UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf

# MU_CHANGE [BEGIN] - Add HwResetSystemLib
[LibraryClasses.X64, LibraryClasses.IA32]
HwResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
# MU_CHANGE [END] - Add HwResetSystemLib

[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
Expand Down

0 comments on commit 15492c1

Please sign in to comment.