Skip to content

Commit

Permalink
MemoryProtectionTestApp: Separate Reset Method Init to Arch Specific …
Browse files Browse the repository at this point in the history
…Files (#376)

## Description

The reset test method is not supported on ARM platforms currently
(support will be added later, but it's not high priority because this
test method often takes 40+ minutes). This PR separates the
initialization of this testing method to architecture specific logic so
the test method is not attempted on ARM platforms.

This also fixes a build error on ARM platforms caused by
DefaultExceptionHandlerLib being included (which does not support
UEFI_APPLICATION without a MU override).

- [x] Impacts functionality?
- **Functionality** - Does the change ultimately impact how firmware
functions?
- Examples: Add a new library, publish a new PPI, update an algorithm,
...
- [ ] Impacts security?
- **Security** - Does the change have a direct security impact on an
application,
    flow, or firmware?
  - Examples: Crypto algorithm change, buffer overflow fix, parameter
    validation improvement, ...
- [ ] Breaking change?
- **Breaking change** - Will anyone consuming this change experience a
break
    in build or boot behavior?
- Examples: Add a new library class, move a module to a different repo,
call
    a function in a new library class in a pre-existing module, ...
- [ ] Includes tests?
  - **Tests** - Does the change include any explicit test code?
  - Examples: Unit tests, integration tests, robot tests, ...
- [ ] Includes documentation?
- **Documentation** - Does the change contain explicit documentation
additions
    outside direct code modifications (and comments)?
- Examples: Update readme file, add feature readme file, link to
documentation
    on an a separate Web page, ...

## How This Was Tested

Running the updated test app on Q35 and SBSA

## Integration Instructions

N/A
  • Loading branch information
TaylorBeebe authored and kenlautner committed Dec 20, 2023
1 parent c209c24 commit 6876d73
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/** @file
Copyright (C) Microsoft Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>

#include <Library/DebugLib.h>
#include <Library/UnitTestLib.h>

/**
Registers the interrupt handler which will be invoked when a page fault occurs.
@retval EFI_SUCCESS Interrupt handler successfully installed
@retval EFI_UNSUPPORTED Installing the interrupt handler is not supported.
@retval others Error occurred during installation.
**/
EFI_STATUS
EFIAPI
RegisterMemoryProtectionTestAppInterruptHandler (
VOID
)
{
// TODO: Add support for reset test method on Arm
return EFI_UNSUPPORTED;
}

/**
Checks if the hardware NX protection is enabled.
@param[in] Context The unit test context.
@retval UNIT_TEST_PASSED Hardware NX protection is enabled.
@retval others Hardware NX protection is not enabled.
**/
UNIT_TEST_STATUS
EFIAPI
UefiHardwareNxProtectionEnabled (
IN UNIT_TEST_CONTEXT Context
)
{
// ARM UEFI only has Stage 1 translation, so the FEAT XNX configuration bit does not apply.
return UNIT_TEST_PASSED;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/** @file -- ArchSpecificFunctions.h
Shared definition of the method between x64 and ARM.
Copyright (C) Microsoft Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef ARCH_SPECIFIC_FUNCTIONS_H_
#define ARCH_SPECIFIC_FUNCTIONS_H_

/**
Registers the interrupt handler which will be invoked when a page fault occurs.
@retval EFI_SUCCESS Interrupt handler successfully installed
@retval EFI_UNSUPPORTED Installing the interrupt handler is not supported.
@retval others Error occurred during installation.
**/
EFI_STATUS
EFIAPI
RegisterMemoryProtectionTestAppInterruptHandler (
VOID
);

/**
Checks if the hardware NX protection is enabled.
@param[in] Context The unit test context.
@retval UNIT_TEST_PASSED Hardware NX protection is enabled.
@retval others Hardware NX protection is not enabled.
**/
UNIT_TEST_STATUS
EFIAPI
UefiHardwareNxProtectionEnabled (
IN UNIT_TEST_CONTEXT Context
);

#endif // ARCH_SPECIFIC_FUNCTIONS_H_

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

#include <Uefi.h>

#include <Protocol/Cpu.h>
#include <Protocol/DebugSupport.h>
#include <Protocol/SmmCommunication.h>
#include <Protocol/MemoryProtectionNonstopMode.h>
#include <Protocol/MemoryProtectionDebug.h>
Expand All @@ -31,8 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/UnitTestBootLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Register/ArchitecturalMsr.h>
#include <Library/ResetSystemLib.h>
#include <Library/HobLib.h>
#include <Library/ExceptionPersistenceLib.h>

Expand All @@ -41,7 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/MmMemoryProtectionSettings.h>

#include "../MemoryProtectionTestCommon.h"
#include "UefiHardwareNxProtectionStub.h"
#include "ArchSpecificFunctions.h"

#define UNIT_TEST_APP_NAME "Memory Protection Test"
#define UNIT_TEST_APP_VERSION "2.0"
Expand All @@ -56,7 +54,6 @@ UINTN mPiSmmCommonCommBufferSize;
MM_MEMORY_PROTECTION_SETTINGS mMmMps;
DXE_MEMORY_PROTECTION_SETTINGS mDxeMps;
VOID *mPiSmmCommonCommBufferAddress = NULL;
EFI_CPU_ARCH_PROTOCOL *mCpu = NULL;
MEMORY_PROTECTION_NONSTOP_MODE_PROTOCOL *mNonstopModeProtocol = NULL;
MEMORY_PROTECTION_DEBUG_PROTOCOL *mMemoryProtectionProtocol = NULL;
EFI_MEMORY_ATTRIBUTE_PROTOCOL *mMemoryAttributeProtocol = NULL;
Expand Down Expand Up @@ -286,27 +283,6 @@ PopulateCpuMpDebugProtocol (
return gBS->LocateProtocol (&gCpuMpDebugProtocolGuid, NULL, (VOID **)&mCpuMpDebugProtocol);
}

/**
Resets the system on interrupt
@param InterruptType Defines the type of interrupt or exception that
occurred on the processor.This parameter is processor architecture specific.
@param SystemContext A pointer to the processor context when
the interrupt occurred on the processor.
**/
VOID
EFIAPI
InterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
// Avoid using runtime services to reset the system because doing so will raise the TPL level
// when it is already on TPL_HIGH. HwResetSystemLib is used here instead to perform a bare-metal reset
// and sidestep this issue.
ResetWarm ();
}

/**
This helper function returns EFI_SUCCESS if the Nonstop protocol is installed.
Expand Down Expand Up @@ -2475,11 +2451,7 @@ DetermineTestMethod (
}

case MemoryProtectionTestReset:
// Uninstall the existing page fault handler
mCpu->RegisterInterruptHandler (mCpu, EXCEPT_IA32_PAGE_FAULT, NULL);

// Install an interrupt handler to reboot on page faults.
if (!EFI_ERROR (mCpu->RegisterInterruptHandler (mCpu, EXCEPT_IA32_PAGE_FAULT, InterruptHandler))) {
if (!EFI_ERROR (RegisterMemoryProtectionTestAppInterruptHandler ())) {
DeterminedTestingMethod = MemoryProtectionTestReset;
break;
}
Expand Down Expand Up @@ -2581,13 +2553,6 @@ MemoryProtectionTestAppEntryPoint (
Status = FetchMemoryProtectionHobEntries ();
ASSERT_EFI_ERROR (Status);

// Find the CPU Architecture Protocol
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to locate gEfiCpuArchProtocolGuid. Status = %r\n", Status));
goto EXIT;
}

// Set up the test framework for running the tests.
Status = InitUnitTestFramework (&Fw, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
if (EFI_ERROR (Status)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@
MemoryProtectionTestApp.c

[Sources.X64]
X64/UefiHardwareNxProtection.c

[Sources.ARM]
Arm/UefiHardwareNxProtection.c
X64/X64Functions.c

[Sources.AARCH64]
Arm/UefiHardwareNxProtection.c
AArch64/AArch64Functions.c

[Packages]
MdePkg/MdePkg.dec
Expand All @@ -52,11 +49,12 @@
BaseLib
ShellLib
UefiLib
CpuExceptionHandlerLib
HwResetSystemLib
HobLib
ExceptionPersistenceLib

[LibraryClasses.X64]
HwResetSystemLib

[Guids]
gMemoryProtectionExceptionHandlerGuid ## CONSUMES
gEfiHobMemoryAllocStackGuid ## CONSUMES
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/** @file
Copyright (c) Microsoft Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>

#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Register/ArchitecturalMsr.h>
#include <Library/UnitTestLib.h>
#include <Library/ResetSystemLib.h>
#include <Protocol/Cpu.h>
#include <Library/UefiBootServicesTableLib.h>

/**
Resets the system on interrupt
@param InterruptType Defines the type of interrupt or exception that
occurred on the processor.This parameter is processor architecture specific.
@param SystemContext A pointer to the processor context when
the interrupt occurred on the processor.
**/
VOID
EFIAPI
InterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
// Avoid using runtime services to reset the system because doing so will raise the TPL level
// when it is already on TPL_HIGH. HwResetSystemLib is used here instead to perform a bare-metal reset
// and sidestep this issue.
ResetWarm ();
}

/**
Registers the interrupt handler which will be invoked when a page fault occurs.
@retval EFI_SUCCESS Interrupt handler successfully installed
@retval EFI_UNSUPPORTED Installing the interrupt handler is not supported.
@retval others Error occurred during installation.
**/
EFI_STATUS
EFIAPI
RegisterMemoryProtectionTestAppInterruptHandler (
VOID
)
{
EFI_CPU_ARCH_PROTOCOL *CpuProtocol = NULL;
EFI_STATUS Status;

// Find the CPU Architecture Protocol
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuProtocol);

if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to locate gEfiCpuArchProtocolGuid. Status = %r\n", Status));
return EFI_INVALID_PARAMETER;
}

// Uninstall the existing page fault handler
CpuProtocol->RegisterInterruptHandler (CpuProtocol, EXCEPT_IA32_PAGE_FAULT, NULL);

return CpuProtocol->RegisterInterruptHandler (CpuProtocol, EXCEPT_IA32_PAGE_FAULT, InterruptHandler);
}

/**
Checks if the hardware NX protection is enabled.
@param[in] Context The unit test context.
@retval UNIT_TEST_PASSED Hardware NX protection is enabled.
@retval others Hardware NX protection is not enabled.
**/
UNIT_TEST_STATUS
EFIAPI
UefiHardwareNxProtectionEnabled (
IN UNIT_TEST_CONTEXT Context
)
{
MSR_IA32_EFER_REGISTER Efer;

Efer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
if (Efer.Bits.NXE == 1) {
return UNIT_TEST_PASSED;
}

UT_LOG_WARNING ("Efer set as 0x%x\n", Efer);
return UNIT_TEST_ERROR_TEST_FAILED;
}

0 comments on commit 6876d73

Please sign in to comment.