public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jordan Justen <jordan.l.justen@intel.com>
To: Laszlo Ersek <lersek@redhat.com>,
	edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Igor Mammedov <imammedo@redhat.com>
Subject: Re: [PATCH 1/1] OvmfPkg/AcpiPlatformDxe: alloc blobs from 64-bit space unless restricted
Date: Mon, 05 Jun 2017 10:47:44 -0700	[thread overview]
Message-ID: <149668486395.8581.9154897144168590783@jljusten-skl> (raw)
In-Reply-To: <20170603154203.29907-2-lersek@redhat.com>

On 2017-06-03 08:42:03, Laszlo Ersek wrote:
> ... by narrower than 8-byte ADD_POINTER references.
> 
> Introduce the CollectRestrictedAllocations() function, which iterates over

How about Collect32BitRestrictedAllocations and similar treatment for
other names that just say 'restricted'?

With that Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

> the linker/loader script, and collects the names of the fw_cfg blobs that
> are referenced by QEMU_LOADER_ADD_POINTER.PointeeFile fields, such that
> QEMU_LOADER_ADD_POINTER.PointerSize is less than 8. This means that the
> pointee blob's address will have to be patched into a narrower-than-8 byte
> pointer field, hence the pointee blob must not be allocated from 64-bit
> address space.
> 
> In ProcessCmdAllocate(), consult these restrictions when setting the
> maximum address for gBS->AllocatePages(). The default is now MAX_UINT64,
> unless restricted like described above to the pre-patch MAX_UINT32 limit.
> 
> In combination with Ard's QEMU commit cb51ac2ffe36 ("hw/arm/virt: generate
> 64-bit addressable ACPI objects", 2017-04-10), this patch enables
> OvmfPkg/AcpiPlatformDxe to work entirely above the 4GB mark.
> 
> (An upcoming / planned aarch64 QEMU machine type will have no RAM under
> 4GB at all. Plus, moving the allocations higher is beneficial to the
> current "virt" machine type as well; in Ard's words: "having all firmware
> allocations inside the same 1 GB (or 512 MB for 64k pages) frame reduces
> the TLB footprint".)
> 
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Suggested-by: Igor Mammedov <imammedo@redhat.com>
> Suggested-by: Gerd Hoffmann <kraxel@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 190 +++++++++++++++++++-
>  1 file changed, 183 insertions(+), 7 deletions(-)
> 
> diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
> index 1bc5fe297a96..7aeb6472188b 100644
> --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
> +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
> @@ -132,14 +132,169 @@ PointerCompare (
>  }
>  
>  
>  /**
> +  Comparator function for two ASCII strings. Can be used as both Key and
> +  UserStruct comparator.
> +
> +  This function exists solely so we can avoid casting &AsciiStrCmp to
> +  ORDERED_COLLECTION_USER_COMPARE and ORDERED_COLLECTION_KEY_COMPARE.
> +
> +  @param[in] AsciiString1  Pointer to the first ASCII string.
> +
> +  @param[in] AsciiString2  Pointer to the second ASCII string.
> +
> +  @return  The return value of AsciiStrCmp (AsciiString1, AsciiString2).
> +**/
> +STATIC
> +INTN
> +EFIAPI
> +AsciiStringCompare (
> +  IN CONST VOID *AsciiString1,
> +  IN CONST VOID *AsciiString2
> +  )
> +{
> +  return AsciiStrCmp (AsciiString1, AsciiString2);
> +}
> +
> +
> +/**
> +  Release the ORDERED_COLLECTION structure populated by
> +  CollectRestrictedAllocations() (below).
> +
> +  This function may be called by CollectRestrictedAllocations() itself, on
> +  the error path.
> +
> +  @param[in] RestrictedAllocations  The ORDERED_COLLECTION structure to
> +                                    release.
> +**/
> +STATIC
> +VOID
> +ReleaseRestrictedAllocations (
> +  IN ORDERED_COLLECTION *RestrictedAllocations
> +)
> +{
> +  ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
> +
> +  for (Entry = OrderedCollectionMin (RestrictedAllocations);
> +       Entry != NULL;
> +       Entry = Entry2) {
> +    Entry2 = OrderedCollectionNext (Entry);
> +    OrderedCollectionDelete (RestrictedAllocations, Entry, NULL);
> +  }
> +  OrderedCollectionUninit (RestrictedAllocations);
> +}
> +
> +
> +/**
> +  Iterate over the linker/loader script, and collect the names of the fw_cfg
> +  blobs that are referenced by QEMU_LOADER_ADD_POINTER.PointeeFile fields, such
> +  that QEMU_LOADER_ADD_POINTER.PointerSize is less than 8. This means that the
> +  pointee blob's address will have to be patched into a narrower-than-8 byte
> +  pointer field, hence the pointee blob must not be allocated from 64-bit
> +  address space.
> +
> +  @param[out] RestrictedAllocations  The ORDERED_COLLECTION structure linking
> +                                     (not copying / owning) such
> +                                     QEMU_LOADER_ADD_POINTER.PointeeFile fields
> +                                     that name the blobs restricted from 64-bit
> +                                     allocation.
> +
> +  @param[in] LoaderStart             Points to the first entry in the
> +                                     linker/loader script.
> +
> +  @param[in] LoaderEnd               Points one past the last entry in the
> +                                     linker/loader script.
> +
> +  @retval EFI_SUCCESS           RestrictedAllocations has been populated.
> +
> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +
> +  @retval EFI_PROTOCOL_ERROR    Invalid linker/loader script contents.
> +**/
> +STATIC
> +EFI_STATUS
> +CollectRestrictedAllocations (
> +  OUT ORDERED_COLLECTION     **RestrictedAllocations,
> +  IN CONST QEMU_LOADER_ENTRY *LoaderStart,
> +  IN CONST QEMU_LOADER_ENTRY *LoaderEnd
> +)
> +{
> +  ORDERED_COLLECTION      *Collection;
> +  CONST QEMU_LOADER_ENTRY *LoaderEntry;
> +  EFI_STATUS              Status;
> +
> +  Collection = OrderedCollectionInit (AsciiStringCompare, AsciiStringCompare);
> +  if (Collection == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
> +    CONST QEMU_LOADER_ADD_POINTER *AddPointer;
> +
> +    if (LoaderEntry->Type != QemuLoaderCmdAddPointer) {
> +      continue;
> +    }
> +    AddPointer = &LoaderEntry->Command.AddPointer;
> +
> +    if (AddPointer->PointerSize >= 8) {
> +      continue;
> +    }
> +
> +    if (AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
> +      DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
> +      Status = EFI_PROTOCOL_ERROR;
> +      goto RollBack;
> +    }
> +
> +    Status = OrderedCollectionInsert (
> +               Collection,
> +               NULL,                           // Entry
> +               (VOID *)AddPointer->PointeeFile
> +               );
> +    switch (Status) {
> +    case EFI_SUCCESS:
> +      DEBUG ((
> +        DEBUG_VERBOSE,
> +        "%a: restricting blob \"%a\" from 64-bit allocation\n",
> +        __FUNCTION__,
> +        AddPointer->PointeeFile
> +        ));
> +      break;
> +    case EFI_ALREADY_STARTED:
> +      //
> +      // The restriction has been recorded already.
> +      //
> +      break;
> +    case EFI_OUT_OF_RESOURCES:
> +      goto RollBack;
> +    default:
> +      ASSERT (FALSE);
> +    }
> +  }
> +
> +  *RestrictedAllocations = Collection;
> +  return EFI_SUCCESS;
> +
> +RollBack:
> +  ReleaseRestrictedAllocations (Collection);
> +  return Status;
> +}
> +
> +
> +/**
>    Process a QEMU_LOADER_ALLOCATE command.
>  
> -  @param[in] Allocate     The QEMU_LOADER_ALLOCATE command to process.
> +  @param[in] Allocate               The QEMU_LOADER_ALLOCATE command to
> +                                    process.
>  
> -  @param[in,out] Tracker  The ORDERED_COLLECTION tracking the BLOB user
> -                          structures created thus far.
> +  @param[in,out] Tracker            The ORDERED_COLLECTION tracking the BLOB
> +                                    user structures created thus far.
> +
> +  @param[in] RestrictedAllocations  The ORDERED_COLLECTION populated by
> +                                    CollectRestrictedAllocations(), naming the
> +                                    fw_cfg blobs that must not be allocated
> +                                    from 64-bit address space.
>  
>    @retval EFI_SUCCESS           An area of whole AcpiNVS pages has been
>                                  allocated for the blob contents, and the
>                                  contents have been saved. A BLOB object (user
> @@ -163,9 +318,10 @@ STATIC
>  EFI_STATUS
>  EFIAPI
>  ProcessCmdAllocate (
>    IN CONST QEMU_LOADER_ALLOCATE *Allocate,
> -  IN OUT ORDERED_COLLECTION     *Tracker
> +  IN OUT ORDERED_COLLECTION     *Tracker,
> +  IN ORDERED_COLLECTION         *RestrictedAllocations
>    )
>  {
>    FIRMWARE_CONFIG_ITEM FwCfgItem;
>    UINTN                FwCfgSize;
> @@ -192,9 +348,12 @@ ProcessCmdAllocate (
>      return Status;
>    }
>  
>    NumPages = EFI_SIZE_TO_PAGES (FwCfgSize);
> -  Address = 0xFFFFFFFF;
> +  Address = MAX_UINT64;
> +  if (OrderedCollectionFind (RestrictedAllocations, Allocate->File) != NULL) {
> +    Address = MAX_UINT32;
> +  }
>    Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, NumPages,
>                    &Address);
>    if (EFI_ERROR (Status)) {
>      return Status;
> @@ -805,8 +964,9 @@ InstallQemuFwCfgTables (
>    CONST QEMU_LOADER_ENTRY  *LoaderEntry, *LoaderEnd;
>    CONST QEMU_LOADER_ENTRY  *WritePointerSubsetEnd;
>    ORIGINAL_ATTRIBUTES      *OriginalPciAttributes;
>    UINTN                    OriginalPciAttributesCount;
> +  ORDERED_COLLECTION       *RestrictedAllocations;
>    S3_CONTEXT               *S3Context;
>    ORDERED_COLLECTION       *Tracker;
>    UINTN                    *InstalledKey;
>    INT32                    Installed;
> @@ -833,17 +993,26 @@ InstallQemuFwCfgTables (
>    QemuFwCfgReadBytes (FwCfgSize, LoaderStart);
>    RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount);
>    LoaderEnd = LoaderStart + FwCfgSize / sizeof *LoaderEntry;
>  
> +  Status = CollectRestrictedAllocations (
> +             &RestrictedAllocations,
> +             LoaderStart,
> +             LoaderEnd
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeLoader;
> +  }
> +
>    S3Context = NULL;
>    if (QemuFwCfgS3Enabled ()) {
>      //
>      // Size the allocation pessimistically, assuming that all commands in the
>      // script are QEMU_LOADER_WRITE_POINTER commands.
>      //
>      Status = AllocateS3Context (&S3Context, LoaderEnd - LoaderStart);
>      if (EFI_ERROR (Status)) {
> -      goto FreeLoader;
> +      goto FreeRestrictedAllocations;
>      }
>    }
>  
>    Tracker = OrderedCollectionInit (BlobCompare, BlobKeyCompare);
> @@ -862,9 +1031,13 @@ InstallQemuFwCfgTables (
>    WritePointerSubsetEnd = LoaderStart;
>    for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
>      switch (LoaderEntry->Type) {
>      case QemuLoaderCmdAllocate:
> -      Status = ProcessCmdAllocate (&LoaderEntry->Command.Allocate, Tracker);
> +      Status = ProcessCmdAllocate (
> +                 &LoaderEntry->Command.Allocate,
> +                 Tracker,
> +                 RestrictedAllocations
> +                 );
>        break;
>  
>      case QemuLoaderCmdAddPointer:
>        Status = ProcessCmdAddPointer (&LoaderEntry->Command.AddPointer,
> @@ -1009,8 +1182,11 @@ FreeS3Context:
>    if (S3Context != NULL) {
>      ReleaseS3Context (S3Context);
>    }
>  
> +FreeRestrictedAllocations:
> +  ReleaseRestrictedAllocations (RestrictedAllocations);
> +
>  FreeLoader:
>    FreePool (LoaderStart);
>  
>    return Status;
> -- 
> 2.9.3
> 


  parent reply	other threads:[~2017-06-05 17:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-03 15:42 [PATCH 0/1] OvmfPkg/AcpiPlatformDxe: alloc blobs from 64-bit space unless restricted Laszlo Ersek
2017-06-03 15:42 ` [PATCH 1/1] " Laszlo Ersek
2017-06-03 18:33   ` Ard Biesheuvel
2017-06-05 17:47   ` Jordan Justen [this message]
2017-06-06 18:16     ` Laszlo Ersek
2017-06-07 23:10       ` Laszlo Ersek
2017-06-08 10:11         ` Ard Biesheuvel
2017-06-08 18:40           ` Laszlo Ersek
2017-06-08 19:05             ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=149668486395.8581.9154897144168590783@jljusten-skl \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox