Reviewed-by: Ray Ni <ray...@intel.com>

> -----Original Message-----
> From: Tan, Dun <dun....@intel.com>
> Sent: Friday, March 24, 2023 2:00 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.d...@intel.com>; Ni, Ray <ray...@intel.com>; Kumar,
> Rahul R <rahul.r.ku...@intel.com>; Gerd Hoffmann <kra...@redhat.com>
> Subject: [Patch V5 08/22] UefiCpuPkg/CpuPageTableLib:Add check for Mask
> and Attr
> 
> For different usage, check if the combination for Mask and
> Attr is valid when creating or updating page table.
> 
> 1.For non-present range
>   1.1Mask.Present is 0 but some other attributes is provided.
>      This case is invalid.
>   1.2Mask.Present is 1 and Attr.Present is 0. In this case,all
>      other attributes should not be provided.
>   1.3Mask.Present is 1 and Attr.Present is 1. In this case,all
>      attributes should be provided to intialize the attribute.
> 
> 2.For present range
>   2.1Mask.Present is 1 and Attr.Present is 0.In this case, all
>      other attributes should not be provided.
> All other usage for present range is permitted.
> In the mentioned cases, 1.2 and 2.1 can be merged into 1 check.
> 
> Signed-off-by: Dun Tan <dun....@intel.com>
> Cc: Eric Dong <eric.d...@intel.com>
> Cc: Ray Ni <ray...@intel.com>
> Cc: Rahul Kumar <rahul1.ku...@intel.com>
> Tested-by: Gerd Hoffmann <kra...@redhat.com>
> Acked-by: Gerd Hoffmann <kra...@redhat.com>
> ---
>  UefiCpuPkg/Include/Library/CpuPageTableLib.h         |  4 ++++
>  UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c | 83
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++-
>  2 files changed, 86 insertions(+), 1 deletion(-)
> 
> diff --git a/UefiCpuPkg/Include/Library/CpuPageTableLib.h
> b/UefiCpuPkg/Include/Library/CpuPageTableLib.h
> index 5f44ece548..4ef4a8b6af 100644
> --- a/UefiCpuPkg/Include/Library/CpuPageTableLib.h
> +++ b/UefiCpuPkg/Include/Library/CpuPageTableLib.h
> @@ -77,6 +77,10 @@ typedef enum {
> 
>    @retval RETURN_UNSUPPORTED        PagingMode is not supported.
>    @retval RETURN_INVALID_PARAMETER  PageTable, BufferSize, Attribute
> or Mask is NULL.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 0 but some other attributes are provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are
> not provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are
> provided.
> +  @retval RETURN_INVALID_PARAMETER  For present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are
> provided.
>    @retval RETURN_INVALID_PARAMETER  *BufferSize is not multiple of 4KB.
>    @retval RETURN_BUFFER_TOO_SMALL   The buffer is too small for page
> table creation/updating.
>                                      BufferSize is updated to indicate the 
> expected buffer size.
> diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
> b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
> index c87eb23248..c0b41472ce 100644
> --- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
> +++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
> @@ -215,6 +215,44 @@ PageTableLibSetPnle (
>    Pnle->Bits.CacheDisabled = 0;
>  }
> 
> +/**
> +  Check if the combination for Attribute and Mask is valid for non-present
> entry.
> +  1.Mask.Present is 0 but some other attributes is provided. This case should
> be invalid.
> +  2.Map non-present range to present. In this case, all attributes should be
> provided.
> +
> +  @param[in] Attribute    The attribute of the linear address range.
> +  @param[in] Mask         The mask used for attribute to check.
> +
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 0 but some other attributes are provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are
> not provided.
> +  @retval RETURN_SUCCESS            The combination for Attribute and Mask is
> valid.
> +**/
> +RETURN_STATUS
> +IsAttributesAndMaskValidForNonPresentEntry (
> +  IN     IA32_MAP_ATTRIBUTE  *Attribute,
> +  IN     IA32_MAP_ATTRIBUTE  *Mask
> +  )
> +{
> +  if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {
> +    //
> +    // Creating new page table or remapping non-present range to present.
> +    //
> +    if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) ||
> (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) ||
> +        (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask-
> >Bits.Pat == 0) || (Mask->Bits.Global == 0) ||
> +        (Mask->Bits.PageTableBaseAddress == 0) || (Mask->Bits.ProtectionKey
> == 0) || (Mask->Bits.Nx == 0))
> +    {
> +      return RETURN_INVALID_PARAMETER;
> +    }
> +  } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) {
> +    //
> +    // Only change other attributes for non-present range is not permitted.
> +    //
> +    return RETURN_INVALID_PARAMETER;
> +  }
> +
> +  return RETURN_SUCCESS;
> +}
> +
>  /**
>    Update page table to map [LinearAddress, LinearAddress + Length) with
> specified attribute in the specified level.
> 
> @@ -237,6 +275,8 @@ PageTableLibSetPnle (
>                                      when a new physical base address is set.
>    @param[in]      Mask              The mask used for attribute. The 
> corresponding
> field in Attribute is ignored if that in Mask is 0.
> 
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 0 but some other attributes are provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are
> not provided.
>    @retval RETURN_SUCCESS            PageTable is created/updated 
> successfully.
>  **/
>  RETURN_STATUS
> @@ -260,6 +300,7 @@ PageTableLibMapInLevel (
>    UINTN               Index;
>    IA32_PAGING_ENTRY   *PagingEntry;
>    UINTN               PagingEntryIndex;
> +  UINTN               PagingEntryIndexEnd;
>    IA32_PAGING_ENTRY   *CurrentPagingEntry;
>    UINT64              RegionLength;
>    UINT64              SubLength;
> @@ -306,6 +347,14 @@ PageTableLibMapInLevel (
>    //
> 
>    if (ParentPagingEntry->Pce.Present == 0) {
> +    //
> +    // [LinearAddress, LinearAddress + Length] contains non-present range.
> +    //
> +    Status = IsAttributesAndMaskValidForNonPresentEntry (Attribute, Mask);
> +    if (RETURN_ERROR (Status)) {
> +      return Status;
> +    }
> +
>      //
>      // The parent entry is CR3 or PML5E/PML4E/PDPTE/PDE.
>      // It does NOT point to an existing page directory.
> @@ -383,6 +432,27 @@ PageTableLibMapInLevel (
>        ParentPagingEntry->Uint64 = ((UINTN)(VOID *)PagingEntry) |
> (ParentPagingEntry->Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40));
>      }
>    } else {
> +    //
> +    // If (LinearAddress + Length - 1) is not in the same ParentPagingEntry
> with (LinearAddress + Offset), then the remaining child PagingEntry
> +    // starting from PagingEntryIndex of ParentPagingEntry is all covered by
> [LinearAddress + Offset, LinearAddress + Length - 1].
> +    //
> +    PagingEntryIndexEnd = (BitFieldRead64 (LinearAddress + Length - 1,
> BitStart + 9, 63) != BitFieldRead64 (LinearAddress + Offset, BitStart + 9, 
> 63)) ?
> 511 :
> +                          (UINTN)BitFieldRead64 (LinearAddress + Length - 1, 
> BitStart,
> BitStart + 9 - 1);
> +    PagingEntry = (IA32_PAGING_ENTRY
> *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry-
> >Pnle);
> +    for (Index = PagingEntryIndex; Index <= PagingEntryIndexEnd; Index++) {
> +      if (PagingEntry[Index].Pce.Present == 0) {
> +        //
> +        // [LinearAddress, LinearAddress + Length] contains non-present 
> range.
> +        //
> +        Status = IsAttributesAndMaskValidForNonPresentEntry (Attribute,
> Mask);
> +        if (RETURN_ERROR (Status)) {
> +          return Status;
> +        }
> +
> +        break;
> +      }
> +    }
> +
>      //
>      // It's a non-leaf entry
>      //
> @@ -430,7 +500,6 @@ PageTableLibMapInLevel (
>          // Update child entries to use restrictive attribute inherited from 
> parent.
>          // e.g.: Set PDE[0-255].ReadWrite = 0
>          //
> -        PagingEntry = (IA32_PAGING_ENTRY
> *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry-
> >Pnle);
>          for (Index = 0; Index < 512; Index++) {
>            if (PagingEntry[Index].Pce.Present == 0) {
>              continue;
> @@ -557,6 +626,10 @@ PageTableLibMapInLevel (
> 
>    @retval RETURN_UNSUPPORTED        PagingMode is not supported.
>    @retval RETURN_INVALID_PARAMETER  PageTable, BufferSize, Attribute
> or Mask is NULL.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 0 but some other attributes are provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 1 but some other attributes are
> not provided.
> +  @retval RETURN_INVALID_PARAMETER  For non-present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are
> provided.
> +  @retval RETURN_INVALID_PARAMETER  For present range, Mask-
> >Bits.Present is 1, Attribute->Bits.Present is 0 but some other attributes are
> provided.
>    @retval RETURN_INVALID_PARAMETER  *BufferSize is not multiple of 4KB.
>    @retval RETURN_BUFFER_TOO_SMALL   The buffer is too small for page
> table creation/updating.
>                                      BufferSize is updated to indicate the 
> expected buffer size.
> @@ -618,6 +691,14 @@ PageTableMap (
>      return RETURN_INVALID_PARAMETER;
>    }
> 
> +  //
> +  // If to map [LinearAddress, LinearAddress + Length] as non-present,
> +  // all attributes except Present should not be provided.
> +  //
> +  if ((Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask-
> >Uint64 > 1)) {
> +    return RETURN_INVALID_PARAMETER;
> +  }
> +
>    MaxLeafLevel     = (IA32_PAGE_LEVEL)(UINT8)PagingMode;
>    MaxLevel         = (IA32_PAGE_LEVEL)(UINT8)(PagingMode >> 8);
>    MaxLinearAddress = LShiftU64 (1, 12 + MaxLevel * 9);
> --
> 2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#101751): https://edk2.groups.io/g/devel/message/101751
Mute This Topic: https://groups.io/mt/97818230/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: 
https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to