123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- /** @file
- SEV-SNP Page Validation functions.
- Copyright (c) 2021 AMD Incorporated. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Uefi/UefiBaseType.h>
- #include <Library/BaseLib.h>
- #include <Library/PcdLib.h>
- #include <Library/DebugLib.h>
- #include <Library/MemEncryptSevLib.h>
- #include "SnpPageStateChange.h"
- #include "VirtualMemory.h"
- typedef struct {
- UINT64 StartAddress;
- UINT64 EndAddress;
- } SNP_PRE_VALIDATED_RANGE;
- STATIC SNP_PRE_VALIDATED_RANGE mPreValidatedRange[] = {
- // The below address range was part of the SEV OVMF metadata, and range
- // should be pre-validated by the Hypervisor.
- {
- FixedPcdGet32 (PcdOvmfSecPageTablesBase),
- FixedPcdGet32 (PcdOvmfPeiMemFvBase),
- },
- // The below range is pre-validated by the Sec/SecMain.c
- {
- FixedPcdGet32 (PcdOvmfSecValidatedStart),
- FixedPcdGet32 (PcdOvmfSecValidatedEnd)
- },
- };
- STATIC
- BOOLEAN
- DetectPreValidatedOverLap (
- IN PHYSICAL_ADDRESS StartAddress,
- IN PHYSICAL_ADDRESS EndAddress,
- OUT SNP_PRE_VALIDATED_RANGE *OverlapRange
- )
- {
- UINTN i;
- //
- // Check if the specified address range exist in pre-validated array.
- //
- for (i = 0; i < ARRAY_SIZE (mPreValidatedRange); i++) {
- if ((mPreValidatedRange[i].StartAddress < EndAddress) &&
- (StartAddress < mPreValidatedRange[i].EndAddress))
- {
- OverlapRange->StartAddress = mPreValidatedRange[i].StartAddress;
- OverlapRange->EndAddress = mPreValidatedRange[i].EndAddress;
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
- @param[in] BaseAddress Base address
- @param[in] NumPages Number of pages starting from the base address
- **/
- VOID
- EFIAPI
- MemEncryptSevSnpPreValidateSystemRam (
- IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages
- )
- {
- PHYSICAL_ADDRESS EndAddress;
- SNP_PRE_VALIDATED_RANGE OverlapRange;
- EFI_STATUS Status;
- if (!MemEncryptSevSnpIsEnabled ()) {
- return;
- }
- EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
- //
- // The page table used in PEI can address up to 4GB memory. If we are asked to
- // validate a range above the 4GB, then create an identity mapping so that the
- // PVALIDATE instruction can execute correctly. If the page table entry is not
- // present then PVALIDATE will #GP.
- //
- if (BaseAddress >= SIZE_4GB) {
- Status = InternalMemEncryptSevCreateIdentityMap1G (
- 0,
- BaseAddress,
- EFI_PAGES_TO_SIZE (NumPages)
- );
- if (EFI_ERROR (Status)) {
- ASSERT (FALSE);
- CpuDeadLoop ();
- }
- }
- while (BaseAddress < EndAddress) {
- //
- // Check if the range overlaps with the pre-validated ranges.
- //
- if (DetectPreValidatedOverLap (BaseAddress, EndAddress, &OverlapRange)) {
- // Validate the non-overlap regions.
- if (BaseAddress < OverlapRange.StartAddress) {
- NumPages = EFI_SIZE_TO_PAGES (OverlapRange.StartAddress - BaseAddress);
- InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
- }
- BaseAddress = OverlapRange.EndAddress;
- continue;
- }
- // Validate the remaining pages.
- NumPages = EFI_SIZE_TO_PAGES (EndAddress - BaseAddress);
- InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
- BaseAddress = EndAddress;
- }
- }
|