public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: SeaBIOS@seabios.org, qemu-devel@nongnu.org, edk2-devel@lists.01.org
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Ben Warren <ben@skyportsystems.com>,
	Dongjiu Geng <gengdongjiu@huawei.com>,
	Igor Mammedov <imammedo@redhat.com>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Leif Lindholm <leif.lindholm@linaro.org>,
	Shannon Zhao <zhaoshenglong@huawei.com>
Subject: [edk2 PATCH 2/3] OvmfPkg/AcpiPlatformDxe: support NOACPI content hint in ALLOCATE command
Date: Fri,  2 Jun 2017 18:03:31 +0200	[thread overview]
Message-ID: <20170602160332.1939-3-lersek@redhat.com> (raw)
In-Reply-To: <20170602160332.1939-1-lersek@redhat.com>

This driver currently relies on a 2nd pass processing of the ADD_POINTER
commands to identify potential ACPI tables in the pointed-to blobs.

In order to tell apart ACPI tables from other operation region-like areas
within pointed-to blobs, we employ a heuristic called "ACPI SDT header
probe" at the target locations of the ADD_POINTER commands. While all ACPI
tables generated by QEMU satisfy this check (i.e., there are no false
negatives), blob content that is *not* an ACPI table has a very slight
chance to pass the test as well (i.e., there is a small chance for false
positives).

In order to suppress this small chance, in QEMU we've historically
formatted opregion-like areas in blobs with a fixed size zero prefix (see
e.g. "docs/specs/vmgenid.txt"), which guarantees that the probe in
OvmfPkg/AcpiPlatformDxe will fail. However, this "suppressor prefix" has
had to be taken into account explicitly in generated AML code -- the
prefix size has had to be added to the patched integer object in AML, at
runtime --, leading to awkwardness.

QEMU is introducing a new hint for the ALLOCATE command, as the most
significant bit of the UINT8 "Zone" field, for disabling the ACPI SDT
header probe in OvmfPkg/AcpiPlatformDxe, for all the pointers that point
into the blob downloaded with the ALLOCATE command. When the bit is set,
the blob is guaranteed to contain no ACPI tables. When the bit is clear,
the behavior is left unchanged.

In ProcessCmdAllocate(), save the hint for later.

In Process2ndPassCmdAddPointer(), consult the saved hint. If QEMU reported
the blob as containing no ACPI table data, then omit the ACPI SDT header
probing and mark the pointed-to blob as unreleasable.

Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Ben Warren <ben@skyportsystems.com>
Cc: Dongjiu Geng <gengdongjiu@huawei.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Shannon Zhao <zhaoshenglong@huawei.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/AcpiPlatformDxe/QemuLoader.h    |  9 +++++-
 OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 29 +++++++++++++++++++-
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/AcpiPlatformDxe/QemuLoader.h b/OvmfPkg/AcpiPlatformDxe/QemuLoader.h
index 437776d86d9a..fa558540e62b 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuLoader.h
+++ b/OvmfPkg/AcpiPlatformDxe/QemuLoader.h
@@ -34,19 +34,26 @@ typedef enum {
 typedef enum {
   QemuLoaderAllocHigh = 1,
   QemuLoaderAllocFSeg
 } QEMU_LOADER_ALLOC_ZONE;
 
+typedef enum {
+  QemuLoaderAllocContentMixed  = 0x00,
+  QemuLoaderAllocContentNoAcpi = 0x80,
+} QEMU_LOADER_ALLOC_CONTENT;
+
 #pragma pack (1)
 //
 // QemuLoaderCmdAllocate: download the fw_cfg file named File, to a buffer
 // allocated in the zone specified by Zone, aligned at a multiple of Alignment.
 //
 typedef struct {
   UINT8  File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
   UINT32 Alignment;                    // power of two
-  UINT8  Zone;                         // QEMU_LOADER_ALLOC_ZONE values
+  UINT8  Zone;                         // One QEMU_LOADER_ALLOC_ZONE value
+                                       // OR-ed together with one
+                                       // QEMU_LOADER_ALLOC_CONTENT value
 } QEMU_LOADER_ALLOCATE;
 
 //
 // QemuLoaderCmdAddPointer: the bytes at
 // [PointerOffset..PointerOffset+PointerSize) in the file PointerFile contain a
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
index 4a7b051288bc..23d543ffe361 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
@@ -36,10 +36,12 @@ typedef struct {
                                         // key.
   UINTN   Size;                         // The number of bytes in this blob.
   UINT8   *Base;                        // Pointer to the blob data.
   BOOLEAN Releasable;                   // TRUE iff the blob should be released
                                         // at the end of processing.
+  BOOLEAN AcpiTablesExcluded;           // TRUE iff QEMU guarantees that the
+                                        // blob contains no ACPI tables
 } BLOB;
 
 
 /**
   Compare a standalone key against a user structure containing an embedded key.
@@ -167,10 +169,12 @@ ProcessCmdAllocate (
   )
 {
   FIRMWARE_CONFIG_ITEM FwCfgItem;
   UINTN                FwCfgSize;
   EFI_STATUS           Status;
+  UINT32               Zone;
+  BOOLEAN              AcpiTablesExcluded;
   UINTN                NumPages;
   EFI_PHYSICAL_ADDRESS Address;
   BLOB                 *Blob;
 
   if (Allocate->File[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
@@ -189,10 +193,18 @@ ProcessCmdAllocate (
     DEBUG ((EFI_D_ERROR, "%a: QemuFwCfgFindFile(\"%a\"): %r\n", __FUNCTION__,
       Allocate->File, Status));
     return Status;
   }
 
+  Zone = Allocate->Zone;
+  if ((Zone & QemuLoaderAllocContentNoAcpi) != 0) {
+    Zone &= ~(UINT32)QemuLoaderAllocContentNoAcpi;
+    AcpiTablesExcluded = TRUE;
+  } else {
+    AcpiTablesExcluded = FALSE;
+  }
+
   NumPages = EFI_SIZE_TO_PAGES (FwCfgSize);
   Address = 0xFFFFFFFF;
   Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, NumPages,
                   &Address);
   if (EFI_ERROR (Status)) {
@@ -206,10 +218,11 @@ ProcessCmdAllocate (
   }
   CopyMem (Blob->File, Allocate->File, QEMU_LOADER_FNAME_SIZE);
   Blob->Size = FwCfgSize;
   Blob->Base = (VOID *)(UINTN)Address;
   Blob->Releasable = TRUE;
+  Blob->AcpiTablesExcluded = AcpiTablesExcluded;
 
   Status = OrderedCollectionInsert (Tracker, NULL, Blob);
   if (Status == RETURN_ALREADY_STARTED) {
     DEBUG ((EFI_D_ERROR, "%a: duplicated file \"%a\"\n", __FUNCTION__,
       Allocate->File));
@@ -595,11 +608,13 @@ UndoCmdWritePointer (
                                target address is encountered for the first
                                time, and it identifies an ACPI table that is
                                different from RDST and XSDT, the table is
                                installed. If a target address is seen for the
                                second or later times, it is skipped without
-                               taking any action.
+                               taking any action. Target addresses that fall
+                               into fw_cfg blobs that QEMU reported in advance
+                               as holding no ACPI content are not even tracked.
 
   @retval EFI_INVALID_PARAMETER  NumInstalled was outside the allowed range on
                                  input.
 
   @retval EFI_OUT_OF_RESOURCES   The AddPointer command identified an ACPI
@@ -651,10 +666,22 @@ Process2ndPassCmdAddPointer (
 
   TrackerEntry = OrderedCollectionFind (Tracker, AddPointer->PointerFile);
   TrackerEntry2 = OrderedCollectionFind (Tracker, AddPointer->PointeeFile);
   Blob = OrderedCollectionUserStruct (TrackerEntry);
   Blob2 = OrderedCollectionUserStruct (TrackerEntry2);
+
+  if (Blob2->AcpiTablesExcluded) {
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "%a: marking blob \"%a\" with no ACPI content as unreleasable\n",
+      __FUNCTION__,
+      AddPointer->PointeeFile
+      ));
+    Blob2->Releasable = FALSE;
+    return EFI_SUCCESS;
+  }
+
   PointerField = Blob->Base + AddPointer->PointerOffset;
   PointerValue = 0;
   CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);
 
   //
-- 
2.9.3




  parent reply	other threads:[~2017-06-02 16:02 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-02 15:45 allocation zone extensions for the firmware linker/loader Laszlo Ersek
2017-06-02 15:59 ` [qemu PATCH 0/7] bios-linker-loader: introduce the NOACPI hint and the 64-bit zone for ALLOCATE Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 1/7] hw/acpi/bios-linker-loader: expose allocation zone as an enum Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 2/7] hw/acpi/bios-linker-loader: introduce "no ACPI tables" content hint for ALLOC Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 3/7] hw/acpi/bios-linker-loader: introduce BIOS_LINKER_LOADER_ALLOC_ZONE_64BIT Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 4/7] hw/acpi/nvdimm: ask the firmware to allocate NVDIMM_DSM_MEM_FILE as NOACPI Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 5/7] hw/acpi/vmgenid: ask the fw to alloc VMGENID_GUID_FW_CFG_FILE " Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 6/7] hw/i386/acpi-build: ask the fw to alloc ACPI_BUILD_TPMLOG_FILE with 64bit/NOACPI Laszlo Ersek
2017-06-02 16:00   ` [qemu PATCH 7/7] hw/arm/virt-acpi-build: make the fw alloc blobs with ACPI tables as 64bit Laszlo Ersek
2017-06-02 16:02 ` [seabios PATCH 0/2] romfile_loader: cope with the UEFI-oriented allocation extensions Laszlo Ersek
2017-06-02 16:02   ` [seabios PATCH 1/2] romfile_loader: alloc: cope with the UEFI-oriented NOACPI content hint Laszlo Ersek
2017-06-02 16:02   ` [seabios PATCH 2/2] romfile_loader: alloc: cope with the UEFI-oriented 64BIT zone hint Laszlo Ersek
2017-06-02 16:03 ` [edk2 PATCH 0/3] OvmfPkg/AcpiPlatformDxe: NOACPI hint and 64-bit zone in fw_cfg blob alloc Laszlo Ersek
2017-06-02 16:03   ` [edk2 PATCH 1/3] OvmfPkg/AcpiPlatformDxe: rename BLOB.HostsOnlyTableData to BLOB.Releasable Laszlo Ersek
2017-06-02 16:03   ` Laszlo Ersek [this message]
2017-06-02 16:03   ` [edk2 PATCH 3/3] OvmfPkg/AcpiPlatformDxe: support 64-bit zone in ALLOCATE command Laszlo Ersek
     [not found] ` <20170602191230-mutt-send-email-mst@kernel.org>
2017-06-02 23:20   ` allocation zone extensions for the firmware linker/loader Laszlo Ersek
2017-06-03  7:36 ` Laszlo Ersek
2017-06-05  9:54   ` [Qemu-devel] " Igor Mammedov
2017-06-06 17:52     ` Laszlo Ersek
     [not found]   ` <20170605185815-mutt-send-email-mst@kernel.org>
2017-06-06 18:10     ` Laszlo Ersek
     [not found]       ` <20170608204207-mutt-send-email-mst@kernel.org>
2017-06-12 16:05         ` Paolo Bonzini

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=20170602160332.1939-3-lersek@redhat.com \
    --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