diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 8e98053994eb..654d3a03905d 100644
--- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -28,14 +28,15 @@ [Defines]
 
 [Sources]
   AcpiPlatform.c
   Qemu.c
   QemuFwCfgAcpi.c
   Xen.c
   EntryPoint.c
+  PciDecoding.c
 
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
   PcAtChipsetPkg/PcAtChipsetPkg.dec
@@ -53,14 +54,15 @@ [LibraryClasses]
   MemoryAllocationLib
   BaseLib
   DxeServicesTableLib
   OrderedCollectionLib
 
 [Protocols]
   gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiPciIoProtocolGuid                         # PROTOCOL SOMETIMES_CONSUMED
 
 [Guids]
   gEfiXenInfoGuid
   gRootBridgesConnectedEventGroupGuid
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
index c073b2a47ec6..d99f2d5a95c7 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
@@ -26,14 +26,15 @@ [Defines]
 #  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
 #
 
 [Sources]
   QemuFwCfgAcpiPlatform.c
   QemuFwCfgAcpi.c
   EntryPoint.c
+  PciDecoding.c
 
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
@@ -43,14 +44,15 @@ [LibraryClasses]
   OrderedCollectionLib
   QemuFwCfgLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
 
 [Protocols]
   gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiPciIoProtocolGuid                         # PROTOCOL SOMETIMES_CONSUMED
 
 [Guids]
   gRootBridgesConnectedEventGroupGuid
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
 
diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
index 55b380b28505..08dd7f8f7dd7 100644
--- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
+++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
@@ -15,22 +15,28 @@
 #ifndef _ACPI_PLATFORM_H_INCLUDED_
 #define _ACPI_PLATFORM_H_INCLUDED_
 
 #include <PiDxe.h>
 
 #include <Protocol/AcpiTable.h>
 #include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
 
 #include <Library/BaseLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/DebugLib.h>
 #include <Library/PcdLib.h>
 
 #include <IndustryStandard/Acpi.h>
 
+typedef struct {
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              PciAttributes;
+} ORIGINAL_ATTRIBUTES;
+
 EFI_STATUS
 EFIAPI
 InstallAcpiTable (
   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
   IN   VOID                          *AcpiTableBuffer,
   IN   UINTN                         AcpiTableBufferSize,
   OUT  UINTN                         *TableKey
@@ -69,9 +75,21 @@ InstallQemuFwCfgTables (
 
 EFI_STATUS
 EFIAPI
 InstallAcpiTables (
   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable
   );
 
+VOID
+EnablePciDecoding (
+  OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+  OUT UINTN               *Count
+  );
+
+VOID
+RestorePciDecoding (
+  IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+  IN UINTN               Count
+  );
+
 #endif
 
diff --git a/OvmfPkg/AcpiPlatformDxe/PciDecoding.c b/OvmfPkg/AcpiPlatformDxe/PciDecoding.c
new file mode 100644
index 000000000000..3b9b12ccc8a6
--- /dev/null
+++ b/OvmfPkg/AcpiPlatformDxe/PciDecoding.c
@@ -0,0 +1,186 @@
+/** @file
+  Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
+  regenerates the ACPI tables.
+
+  Copyright (C) 2016, Red Hat, Inc.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which 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.
+**/
+
+#include <Library/MemoryAllocationLib.h>
+
+#include "AcpiPlatform.h"
+
+
+/**
+  Collect all PciIo protocol instances in the system. Save their original
+  attributes, and enable IO and MMIO decoding for each.
+
+  This is a best effort function; it doesn't return status codes. Its
+  caller is supposed to proceed even if this function fails.
+
+  @param[out] OriginalAttributes  On output, a dynamically allocated array of
+                                  ORIGINAL_ATTRIBUTES elements. The array lists
+                                  the PciIo protocol instances found in the
+                                  system at the time of the call, plus the
+                                  original PCI attributes for each.
+
+                                  Before returning, the function enables IO and
+                                  MMIO decoding for each PciIo instance it
+                                  finds.
+
+                                  On error, or when no such instances are
+                                  found, OriginalAttributes is set to NULL.
+
+  @param[out] Count               On output, the number of elements in
+                                  OriginalAttributes. On error it is set to
+                                  zero.
+**/
+VOID
+EnablePciDecoding (
+  OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+  OUT UINTN               *Count
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               NoHandles;
+  EFI_HANDLE          *Handles;
+  ORIGINAL_ATTRIBUTES *OrigAttrs;
+  UINTN               Idx;
+
+  *OriginalAttributes = NULL;
+  *Count              = 0;
+
+  if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+    //
+    // The platform downloads ACPI tables from QEMU in general, but there are
+    // no root bridges in this execution. We're done.
+    //
+    return;
+  }
+
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,
+                  NULL /* SearchKey */, &NoHandles, &Handles);
+  if (Status == EFI_NOT_FOUND) {
+    //
+    // No PCI devices were found on either of the root bridges. We're done.
+    //
+    return;
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
+      Status));
+    return;
+  }
+
+  OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
+  if (OrigAttrs == NULL) {
+    DEBUG ((EFI_D_WARN, "%a: AllocatePool(): out of resources\n",
+      __FUNCTION__));
+    goto FreeHandles;
+  }
+
+  for (Idx = 0; Idx < NoHandles; ++Idx) {
+    EFI_PCI_IO_PROTOCOL *PciIo;
+
+    //
+    // Look up PciIo on the handle and stash it
+    //
+    Status = gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,
+                    (VOID**)&PciIo);
+    ASSERT_EFI_ERROR (Status);
+    OrigAttrs[Idx].PciIo = PciIo;
+
+    //
+    // Stash the current attributes
+    //
+    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
+                      &OrigAttrs[Idx].PciAttributes);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
+        __FUNCTION__, Status));
+      goto RestoreAttributes;
+    }
+
+    //
+    // Enable IO and MMIO decoding
+    //
+    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
+                      EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY,
+                      NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",
+        __FUNCTION__, Status));
+      goto RestoreAttributes;
+    }
+  }
+
+  //
+  // Success
+  //
+  FreePool (Handles);
+  *OriginalAttributes = OrigAttrs;
+  *Count              = NoHandles;
+  return;
+
+RestoreAttributes:
+  while (Idx > 0) {
+    --Idx;
+    OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,
+                            EfiPciIoAttributeOperationSet,
+                            OrigAttrs[Idx].PciAttributes,
+                            NULL
+                            );
+  }
+  FreePool (OrigAttrs);
+
+FreeHandles:
+  FreePool (Handles);
+}
+
+
+/**
+  Restore the original PCI attributes saved with EnablePciDecoding().
+
+  @param[in] OriginalAttributes  The array allocated and populated by
+                                 EnablePciDecoding(). This parameter may be
+                                 NULL. If OriginalAttributes is NULL, then the
+                                 function is a no-op; otherwise the PciIo
+                                 attributes will be restored, and the
+                                 OriginalAttributes array will be freed.
+
+  @param[in] Count               The Count value stored by EnablePciDecoding(),
+                                 the number of elements in OriginalAttributes.
+                                 Count may be zero if and only if
+                                 OriginalAttributes is NULL.
+**/
+VOID
+RestorePciDecoding (
+  IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+  IN UINTN               Count
+  )
+{
+  UINTN Idx;
+
+  ASSERT ((OriginalAttributes == NULL) == (Count == 0));
+  if (OriginalAttributes == NULL) {
+    return;
+  }
+
+  for (Idx = 0; Idx < Count; ++Idx) {
+    OriginalAttributes[Idx].PciIo->Attributes (
+                                     OriginalAttributes[Idx].PciIo,
+                                     EfiPciIoAttributeOperationSet,
+                                     OriginalAttributes[Idx].PciAttributes,
+                                     NULL
+                                     );
+  }
+  FreePool (OriginalAttributes);
+}
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
index 81620448a046..faaff3757cdb 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
@@ -557,14 +557,16 @@ InstallQemuFwCfgTables (
   )
 {
   EFI_STATUS               Status;
   FIRMWARE_CONFIG_ITEM     FwCfgItem;
   UINTN                    FwCfgSize;
   QEMU_LOADER_ENTRY        *LoaderStart;
   CONST QEMU_LOADER_ENTRY  *LoaderEntry, *LoaderEnd;
+  ORIGINAL_ATTRIBUTES      *OriginalPciAttributes;
+  UINTN                    OriginalPciAttributesCount;
   ORDERED_COLLECTION       *Tracker;
   UINTN                    *InstalledKey;
   INT32                    Installed;
   ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2;
 
   Status = QemuFwCfgFindFile ("etc/table-loader", &FwCfgItem, &FwCfgSize);
   if (EFI_ERROR (Status)) {
@@ -576,16 +578,18 @@ InstallQemuFwCfgTables (
     return EFI_PROTOCOL_ERROR;
   }
 
   LoaderStart = AllocatePool (FwCfgSize);
   if (LoaderStart == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
+  EnablePciDecoding (&OriginalPciAttributes, &OriginalPciAttributesCount);
   QemuFwCfgSelectItem (FwCfgItem);
   QemuFwCfgReadBytes (FwCfgSize, LoaderStart);
+  RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount);
   LoaderEnd = LoaderStart + FwCfgSize / sizeof *LoaderEntry;
 
   Tracker = OrderedCollectionInit (BlobCompare, BlobKeyCompare);
   if (Tracker == NULL) {
     Status = EFI_OUT_OF_RESOURCES;
     goto FreeLoader;
   }
