Reporting Issues
Bug 1859 - placing the q35 PCIEXBAR above the 32-bit MMIO aperture causes QEMU to generate an invalid ACPI \_SB.PCI0._CRS object
Summary: placing the q35 PCIEXBAR above the 32-bit MMIO aperture causes QEMU to genera...
Status: RESOLVED FIXED
Alias: None
Product: EDK2
Classification: Unclassified
Component: Code (show other bugs)
Version: Current
Hardware: All All
: Lowest normal
Assignee: Laszlo Ersek
URL:
Keywords: regression
Depends on:
Blocks:
 
Reported: 2019-05-29 04:25 UTC by Laszlo Ersek
Modified: 2019-06-03 14:10 UTC (History)
4 users (show)

See Also:
EDK II Code First industry standard specifications: ---
Branch URL:
Release(s) the issue is observed: EDK II Master
The OS the target platform is running: ---
Package: OvmfPkg
Release(s) the issues must be fixed: EDK II Master
Tianocore documents:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Laszlo Ersek 2019-05-29 04:25:17 UTC
(Symptom originally reported by Gerd Hoffmann.)

In commit 75136b29541b ("OvmfPkg/PlatformPei: reorder the 32-bit PCI
window vs. the PCIEXBAR on q35", 2019-05-16), made for bug 1814, we
raised the base of the MMCONFIG range to 0xE000_0000, and moved the
32-bit PCI MMIO aperture underneath.

This causes QEMU to generate an invalid _CRS object in the ACPI DSDT,
for \_SB.PCI0. QEMU appears to assume that the PCIEXBAR is at the lower
address, and clamps the 32-bit PCI MMIO aperture, exposed in the CRS,
above it. Partial quote from the decompiled, generated DSDT:

DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPCDSDT", 0x00000001)
{
    Scope (\_SB.PCI0)
    {
        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
        {
            DWordMemory (ResourceProducer, PosDecode, MinFixed,
                         MaxFixed, NonCacheable, ReadWrite,
                0x00000000,         // Granularity
                0xF0000000,         // Range Minimum
                0xFEBFFFFF,         // Range Maximum
                0x00000000,         // Translation Offset
                0x0EC00000,         // Length
                ,, , AddressRangeMemory, TypeStatic)
        })
    }
}

As a consequence, the OS finds that the 32-bit MMIO BARs of all PCI
devices, originally (correctly) enumerated / assigned by the firmware,
fall outside of the _CRS. The OS (both Windows and Linux) silently
re-assign these resources. Thus, the change in behavior is mostly
invisible to users -- except when there are many (or large) 32-bit MMIO
BARs, the firmware can fit them (in the original, intended aperture),
but the OS cannot (into the small [0xF000_0000, 0xFEBF_FFFF] aperture).

QEMU is under investigation, but the fix could be intrusive and run the
risk of regressions.

A workaround in OVMF could look as follows:

- Preserve the logic added for bug 1814 in case of i440fx. i440fx is not
  affected, as it has no PCIEXBAR.

- For Q35, move the PCIEXBAR to a low address again, and move the 32-bit
  MMIO aperture above it.

- Use fixed (build-time) constants for both. Do not depend on the 32-bit
  RAM size. Making PcdPciExpressBaseAddress a dynamic PCD is intrusive
  and could cause further regressions.

- Effectively return to the pre-BZ-1814 state, except raise
  PcdPciExpressBaseAddress from 0x80000000 to a higher constant.

- We have to set PcdPciExpressBaseAddress to 0xB000_0000 as a minimum,
  as QEMU may allow 32-bit RAM to extend that high (the exclusive end
  may be at 0xB000_0000).

- However, the PcdPciExpressBaseAddress value is connected to the MTRR
  setup as well. Both the EXBAR and the 32-bit MMIO aperture should be
  marked UC.

  - If we place the EXBAR at 0xB000_0000, then we will need *two*
    variable MTRRs: one at 0xB000_0000 (size 256MB), another at
    0xC000_0000 (size 1GB). This will provide the OS with the following
    32-bit MMIO aperture: [0xC000_0000, 0xFC00_0000), i.e. 960 MB.

  - If we place the EXBAR at 0xC000_0000, then we can stick with just
    one variable MTRR: at 0xC000_0000 (size 1GB). This will provide the
    OS with the following 32-bit MMIO aperture: [0xD000_0000,
    0xFC00_0000), i.e. 704 MB.

  - Either way, the low RAM MTRR setup in the QemuInitializeRam()
    function would have to depend on the board type.
Comment 1 Laszlo Ersek 2019-05-29 11:13:47 UTC
Posted:
- [PATCH for-edk2-stable201905 0/6]
  work around a QEMU issue triggered by the original TianoCore#1814 fix
- http://mid.mail-archive.com/20190529151209.17503-1-lersek@redhat.com
- https://edk2.groups.io/g/devel/message/41624
Comment 2 Laszlo Ersek 2019-06-03 07:34:20 UTC
(In reply to Laszlo Ersek from comment #0)

> As a consequence, the OS finds that the 32-bit MMIO BARs of all PCI
> devices, originally (correctly) enumerated / assigned by the firmware,
> fall outside of the _CRS. The OS (both Windows and Linux) silently
> re-assign these resources. Thus, the change in behavior is mostly
> invisible to users -- except when there are many (or large) 32-bit MMIO
> BARs, the firmware can fit them (in the original, intended aperture),
> but the OS cannot (into the small [0xF000_0000, 0xFEBF_FFFF] aperture).

Gerd confirmed elsewhere that the symptom can be worse than the above -- some guest OSes do not cope with the fact as well as above that the programmed resources fall outside of the _CRS. Gerd wrote namely that the  RHEL-7 kernel for example booted very slowly, likely due to VGA framebuffer reassignment while efifb ran on it.
Comment 3 Laszlo Ersek 2019-06-03 14:10:37 UTC
(In reply to Laszlo Ersek from comment #1)
> Posted:
> - [PATCH for-edk2-stable201905 0/6]
>   work around a QEMU issue triggered by the original TianoCore#1814 fix
> - http://mid.mail-archive.com/20190529151209.17503-1-lersek@redhat.com
> - https://edk2.groups.io/g/devel/message/41624

Pushed as commit range f03859ea6c8f..49edde15230a.