QEMU's test suite includes a set of cases called "BIOS tables test". Among
other things, it locates the RSD PTR ACPI table in guest RAM, and then
(chasing pointers to other ACPI tables) performs various sanity checks on
the QEMU-generated and firmware-installed tables.

Currently this set of test cases doesn't work with UEFI guests, because
the ACPI spec's definition for locating the RSD PTR in UEFI guests is a
lot harder to implement from the hypervisor side -- just with raw guest
memory access -- than it is when scraping the memory of BIOS guests.

Introduce a signature GUID, and a small, MB-aligned structure, identified
by the GUID. The hypervisor should loop over all MB-aligned pages in guest
RAM until one matches the signature GUID at offset 0, at which point the
hypervisor can fetch the RSDP address field(s) from the structure.

QEMU's test logic currently spins on a pre-determined guest address, until
that address assumes a magic value. The method described in this patch is
conceptually the same ("busy loop until match is found"), except there is
no hard-coded address. This plays a lot more nicely with UEFI guest
firmware (we'll be able to use the normal page allocation UEFI service).
Given the size of EFI_GUID (16 bytes -- 128 bits), mismatches should be
astronomically unlikely. In addition, given the typical guest RAM size for
such tests (128 MB), there are 128 locations to check in one iteration of
the "outer" loop, which shouldn't introduce an intolerable delay after the
guest stores the RSDP address(es), and then the GUID.

The GUID that the hypervisor should search for is

  AB87A6B1-2034-BDA0-71BD-375007757785

Expressed as a byte array:

  {
    0xb1, 0xa6, 0x87, 0xab,
    0x34, 0x20,
    0xa0, 0xbd,
    0x71, 0xbd, 0x37, 0x50, 0x07, 0x75, 0x77, 0x85
  }

Note that in the patch, we define "gAcpiTestSupportGuid" with all bits
inverted. This is a simple method to prevent the UEFI binaries that
incorporate "gAcpiTestSupportGuid" from matching the actual GUID in guest
RAM.

Cc: Anthony Perard <anthony.per...@citrix.com>
Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>
Cc: Drew Jones <drjo...@redhat.com>
Cc: Igor Mammedov <imamm...@redhat.com>
Cc: Jordan Justen <jordan.l.jus...@intel.com>
Cc: Julien Grall <julien.gr...@linaro.org>
Cc: Philippe Mathieu-Daudé <phi...@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 OvmfPkg/OvmfPkg.dec                    |  1 +
 OvmfPkg/Include/Guid/AcpiTestSupport.h | 67 ++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 7666297cf8f1..e8c7d9423f43 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -73,11 +73,12 @@ [LibraryClasses]
 [Guids]
   gUefiOvmfPkgTokenSpaceGuid          = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 
0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
   gEfiXenInfoGuid                     = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 
0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
   gOvmfPlatformConfigGuid             = {0x7235c51c, 0x0c80, 0x4cab, {0x87, 
0xac, 0x3b, 0x08, 0x4a, 0x63, 0x04, 0xb1}}
   gVirtioMmioTransportGuid            = {0x837dca9e, 0xe874, 0x4d82, {0xb2, 
0x9a, 0x23, 0xfe, 0x0e, 0x23, 0xd1, 0xe2}}
   gQemuRamfbGuid                      = {0x557423a1, 0x63ab, 0x406c, {0xbe, 
0x7e, 0x91, 0xcd, 0xbc, 0x08, 0xc4, 0x57}}
   gXenBusRootDeviceGuid               = {0xa732241f, 0x383d, 0x4d9c, {0x8a, 
0xe1, 0x8e, 0x09, 0x83, 0x75, 0x89, 0xd7}}
   gRootBridgesConnectedEventGroupGuid = {0x24a2d66f, 0xeedd, 0x4086, {0x90, 
0x42, 0xf2, 0x6e, 0x47, 0x97, 0xee, 0x69}}
+  gAcpiTestSupportGuid                = {0x5478594e, 0xdfcb, 0x425f, {0x8e, 
0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a}}
 
 [Protocols]
   gVirtioDeviceProtocolGuid           = {0xfa920010, 0x6785, 0x4941, {0xb6, 
0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
diff --git a/OvmfPkg/Include/Guid/AcpiTestSupport.h 
b/OvmfPkg/Include/Guid/AcpiTestSupport.h
new file mode 100644
index 000000000000..8526f2bfb391
--- /dev/null
+++ b/OvmfPkg/Include/Guid/AcpiTestSupport.h
@@ -0,0 +1,67 @@
+/** @file
+  Expose the address(es) of the ACPI RSD PTR table(s) in a MB-aligned structure
+  to the hypervisor.
+
+  The hypervisor locates the MB-aligned structure based on the signature GUID
+  that is at offset 0 in the structure. Once the RSD PTR address(es) are
+  retrieved, the hypervisor may perform various ACPI checks.
+
+  This feature is a development aid, for supporting ACPI table unit tests in
+  hypervisors. Do not enable in production builds.
+
+  Copyright (C) 2018, Red Hat, Inc.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution. The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __ACPI_TEST_SUPPORT_H__
+#define __ACPI_TEST_SUPPORT_H__
+
+#include <Uefi/UefiBaseType.h>
+
+#define ACPI_TEST_SUPPORT_GUID                         \
+  {                                                    \
+    0x5478594e,                                        \
+    0xdfcb,                                            \
+    0x425f,                                            \
+    { 0x8e, 0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a } \
+  }
+
+extern EFI_GUID gAcpiTestSupportGuid;
+
+//
+// The following structure must be allocated in Boot Services Data type memory,
+// aligned at a 1MB boundary.
+//
+#pragma pack (1)
+typedef struct {
+  //
+  // The signature GUID is written to the MB-aligned structure from
+  // gAcpiTestSupportGuid, but with all bits inverted. That's the actual GUID
+  // value that the hypervisor should look for at each MB boundary, looping
+  // over all guest RAM pages with that alignment, until a match is found. The
+  // bit-flipping occurs in order not to store the actual GUID in any UEFI
+  // executable, which might confuse guest memory analysis. Note that EFI_GUID
+  // has little endian representation.
+  //
+  EFI_GUID             InverseSignatureGuid;
+  //
+  // The Rsdp10 and Rsdp20 fields may be read when the signature GUID matches.
+  // Rsdp10 is the guest-physical address of the ACPI 1.0 specification RSD PTR
+  // table, in 8-byte little endian representation. Rsdp20 is the same, for the
+  // ACPI 2.0 or later specification RSD PTR table. Each of these fields may be
+  // zero (independently of the other) if the UEFI System Table does not
+  // provide the corresponding UEFI Configuration Table.
+  //
+  EFI_PHYSICAL_ADDRESS Rsdp10;
+  EFI_PHYSICAL_ADDRESS Rsdp20;
+} ACPI_TEST_SUPPORT;
+#pragma pack ()
+
+#endif // __ACPI_TEST_SUPPORT_H__
-- 
2.19.1.3.g30247aa5d201


_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to