At the moment, the "UefiCpuPkg/Universal/Acpi/S3Resume2Pei" module doesn't
support S3 resume if the platform has SMM enabled and the PEI phase is
built for X64. We document this in the README, but it is not conspicuous
enough.
Replace the "fine print" in the README with a runtime check in
PlatformPei.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19070 6f19259b-4bc3-4df7-8a09-765794883524
Since our fake LockBox must not be selected with -D SMM_REQUIRE (see the
previous patch), it makes sense to set aside memory for it only if -D
SMM_REQUIRE is absent. Modify InitializeRamRegions() accordingly.
This patch completes the -D SMM_REQUIRE-related tweaking of the special
OVMF memory areas.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19047 6f19259b-4bc3-4df7-8a09-765794883524
PlatformPei calls GetSystemMemorySizeBelow4gb() in three locations:
- PublishPeiMemory(): on normal boot, the permanent PEI RAM is installed
so that it ends with the RAM below 4GB,
- QemuInitializeRam(): on normal boot, memory resource descriptor HOBs are
created for the RAM below 4GB; plus MTRR attributes are set
(independently of S3 vs. normal boot)
- MemMapInitialization(): an MMIO resource descriptor HOB is created for
PCI resource allocation, on normal boot, starting at max(RAM below 4GB,
2GB).
The first two of these is adjusted for the configured TSEG size, if
PcdSmmSmramRequire is set:
- In PublishPeiMemory(), the permanent PEI RAM is kept under TSEG.
- In QemuInitializeRam(), we must keep the DXE out of TSEG.
One idea would be to simply trim the [1MB .. LowerMemorySize] memory
resource descriptor HOB, leaving a hole for TSEG in the memory space
map.
The SMM IPL will however want to massage the caching attributes of the
SMRAM range that it loads the SMM core into, with
gDS->SetMemorySpaceAttributes(), and that won't work on a hole. So,
instead of trimming this range, split the TSEG area off, and report it
as a cacheable reserved memory resource.
Finally, since reserved memory can be allocated too, pre-allocate TSEG
in InitializeRamRegions(), after QemuInitializeRam() returns. (Note that
this step alone does not suffice without the resource descriptor HOB
trickery: if we omit that, then the DXE IPL PEIM fails to load and start
the DXE core.)
- In MemMapInitialization(), the start of the PCI MMIO range is not
affected.
We choose the largest option (8MB) for the default TSEG size. Michael
Kinney pointed out that the SMBASE relocation in PiSmmCpuDxeSmm consumes
SMRAM proportionally to the number of CPUs. From the three options
available, he reported that 8MB was both necessary and sufficient for the
SMBASE relocation to succeed with 255 CPUs:
- http://thread.gmane.org/gmane.comp.bios.edk2.devel/3020/focus=3137
- http://thread.gmane.org/gmane.comp.bios.edk2.devel/3020/focus=3177
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19039 6f19259b-4bc3-4df7-8a09-765794883524
AddReservedMemoryBaseSizeHob() should be able to set the same resource
attributes for reserved memory as AddMemoryBaseSizeHob() sets for system
memory. Add a new parameter called "Cacheable" to
AddReservedMemoryBaseSizeHob(), and set it to FALSE in the only caller we
have at the moment.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19038 6f19259b-4bc3-4df7-8a09-765794883524
If OVMF was built with -D SMM_REQUIRE, that implies that the runtime OS is
not trusted and we should defend against it tampering with the firmware's
data.
One such datum is the PEI firmware volume (PEIFV). Normally PEIFV is
decompressed on the first boot by SEC, then the OS preserves it across S3
suspend-resume cycles; at S3 resume SEC just reuses the originally
decompressed PEIFV.
However, if we don't trust the OS, then SEC must decompress PEIFV from the
pristine flash every time, lest we execute OS-injected code or work with
OS-injected data.
Due to how FVMAIN_COMPACT is organized, we can't decompress just PEIFV;
the decompression brings DXEFV with itself, plus it uses a temporary
output buffer and a scratch buffer too, which even reach above the end of
the finally installed DXEFV. For this reason we must keep away a
non-malicious OS from DXEFV too, plus the memory up to
PcdOvmfDecomprScratchEnd.
The delay introduced by the LZMA decompression on S3 resume is negligible.
If -D SMM_REQUIRE is not specified, then PcdSmmSmramRequire remains FALSE
(from the DEC file), and then this patch has no effect (not counting some
changed debug messages).
If QEMU doesn't support S3 (or the user disabled it on the QEMU command
line), then this patch has no effect also.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19037 6f19259b-4bc3-4df7-8a09-765794883524
Control them with:
-fw_cfg name=opt/ovmf/PcdPropertiesTableEnable,file=no.txt \
-fw_cfg name=opt/ovmf/PcdSetNxForStack,file=yes.txt
where the contents of the text files can be
[0nN1yY](\n|\r\n)?
The macro trickery is not optimal, but it is caused by PcdSetBool(), which
is itself a macro, and can only take open-coded PCD names (ie. no
variables, like function parameters).
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18471 6f19259b-4bc3-4df7-8a09-765794883524
The logic we have in place for i440fx does not work reliably on q35. For
example, if the guest has 2GB of RAM, we allow the PCI root bridge driver
to allocate the legacy video RAM BAR from the [2048 MB, 2816 MB] range,
which falls strictly outside of the Q35 PCI host MMIO aperture that QEMU
configures, and advertizes in ACPI.
In turn, PCI BARs that exist outside of the PCI host aperture that is
exposed in ACPI break Windows guests.
Allocating PCI MMIO resources at or above 3GB on Q35 ensures that we stay
within QEMU's aperture. (See the "w32.begin" assignments in
"hw/pci-host/q35.c".) Furthermore, in pc_q35_init() (file
"hw/i386/pc_q35.c"), QEMU ensures that the low RAM never "leaks" above
3GB.
The i440fx logic is left unchanged.
The Windows guest malfunction on Q35 was reported by Jon Panozzo of Lime
Technology, Inc.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jon Panozzo <jonp@lime-technology.com>
Cc: "Gabriel L. Somlo" <somlo@cmu.edu>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Jonathan Panozzo <jonp@lime-technology.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18393 6f19259b-4bc3-4df7-8a09-765794883524
We have an old bug in BootModeInitialization(): firmware is supposed to
clear the CMOS register 0xF after reading it for the last time. QEMU only
sets this register to 0xFE in "hw/timer/mc146818rtc.c", function
rtc_notify_suspend(), and never clears it. However, SeaBIOS does clear it
in "src/post.c" and "src/resume.c", so let's follow suit.
We've never noticed this until now because the register gets mysteriously
cleared on non-resume reboots when OVMF runs on qemu-system-x86_64. But on
qemu-system-i386, this bug breaks a (suspend, resume, reboot) triplet:
after the last step OVMF thinks it's resuming because when it actually
resumed (in the middle step), it failed to clear the register.
BootModeInitialization() is the perfect function to clear the register,
right after setting mBootMode: the function is executed on both normal
boot and on S3 resume; it succeeds DebugDumpCmos() -- so the dump is not
affected by this patch --; and everything that relies on S3 vs. normal
boot after we clear the register uses mBootMode anyway.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18391 6f19259b-4bc3-4df7-8a09-765794883524
This patch de-duplicates the logic added in commit
OvmfPkg: PlatformPei: set SMBIOS entry point version dynamically
(git 37baf06b, SVN r17676) by hooking DetectSmbiosVersionLib into
SmbiosDxe.
Although said commit was supposed to work with SMBIOS 3.0 payloads from
QEMU, in practice that never worked, because the size / signature checks
in SmbiosVersionInitialization() would always fail, due to the SMBIOS 3.0
entry point being structurally different. Therefore this patch doesn't
regress OvmfPkg.
Cc: Wei Huang <wei@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gabriel L. Somlo <somlo@cmu.edu>
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18175 6f19259b-4bc3-4df7-8a09-765794883524
At the moment we work with a UC default MTRR type, and set three memory
ranges to WB:
- [0, 640 KB),
- [1 MB, LowerMemorySize),
- [4 GB, 4 GB + UpperMemorySize).
Unfortunately, coverage for the third range can fail with a high
likelihood. If the alignment of the base (ie. 4 GB) and the alignment of
the size (UpperMemorySize) differ, then MtrrLib creates a series of
variable MTRR entries, with power-of-two sized MTRR masks. And, it's
really easy to run out of variable MTRR entries, dependent on the
alignment difference.
This is a problem because a Linux guest will loudly reject any high memory
that is not covered my MTRR.
So, let's follow the inverse pattern (loosely inspired by SeaBIOS):
- flip the MTRR default type to WB,
- set [0, 640 KB) to WB -- fixed MTRRs have precedence over the default
type and variable MTRRs, so we can't avoid this,
- set [640 KB, 1 MB) to UC -- implemented with fixed MTRRs,
- set [LowerMemorySize, 4 GB) to UC -- should succeed with variable MTRRs
more likely than the other scheme (due to less chaotic alignment
differences).
Effects of this patch can be observed by setting DEBUG_CACHE (0x00200000)
in PcdDebugPrintErrorLevel.
Cc: Maoming <maoming.maoming@huawei.com>
Cc: Huangpeng (Peter) <peter.huangpeng@huawei.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Maoming <maoming.maoming@huawei.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17722 6f19259b-4bc3-4df7-8a09-765794883524
Maoming reported that guest memory sizes equal to or larger than 64GB
were not correctly handled by OVMF.
Enabling the DEBUG_GCD (0x00100000) bit in PcdDebugPrintErrorLevel, and
starting QEMU with 64GB guest RAM size, I found the following error in the
OVMF debug log:
> GCD:AddMemorySpace(Base=0000000100000000,Length=0000000F40000000)
> GcdMemoryType = Reserved
> Capabilities = 030000000000000F
> Status = Unsupported
This message is emitted when the DXE core is initializing the memory space
map, processing the "above 4GB" memory resource descriptor HOB that was
created by OVMF's QemuInitializeRam() function (see "UpperMemorySize").
The DXE core's call chain fails in:
CoreInternalAddMemorySpace() [MdeModulePkg/Core/Dxe/Gcd/Gcd.c]
CoreConvertSpace()
//
// Search for the list of descriptors that cover the range BaseAddress
// to BaseAddress+Length
//
CoreSearchGcdMapEntry()
CoreSearchGcdMapEntry() fails because the one entry (with type
"nonexistent") in the initial GCD memory space map is too small, and
cannot be split to cover the memory space range being added:
> GCD:Initial GCD Memory Space Map
> GCDMemType Range Capabilities Attributes
> ========== ================================= ================ ================
> NonExist 0000000000000000-0000000FFFFFFFFF 0000000000000000 0000000000000000
The size of this initial entry is determined from the CPU HOB
(CoreInitializeGcdServices()).
Set the SizeOfMemorySpace field in the CPU HOB to mPhysMemAddressWidth,
which is the narrowest valid value to cover the entire guest RAM.
Reported-by: Maoming <maoming.maoming@huawei.com>
Cc: Maoming <maoming.maoming@huawei.com>
Cc: Huangpeng (Peter) <peter.huangpeng@huawei.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Wei Liu <wei.liu2@citrix.com>
Tested-by: Maoming <maoming.maoming@huawei.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17720 6f19259b-4bc3-4df7-8a09-765794883524
We'll soon increase the maximum guest-physical RAM size supported by OVMF.
For more RAM, the DXE IPL is going to build more page tables, and for that
it's going to need a bigger chunk from the permanent PEI RAM.
Otherwise CreateIdentityMappingPageTables() would fail with:
> DXE IPL Entry
> Loading PEIM at 0x000BFF61000 EntryPoint=0x000BFF61260 DxeCore.efi
> Loading DXE CORE at 0x000BFF61000 EntryPoint=0x000BFF61260
> AllocatePages failed: No 0x40201 Pages is available.
> There is only left 0x3F1F pages memory resource to be allocated.
> ASSERT .../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c(123):
> BigPageAddress != 0
(The above example belongs to the artificially high, maximal address width
of 52, clamped by the DXE core to 48. The address width of 48 bits
corresponds to 256 TB or RAM, and requires a bit more than 1GB for paging
structures.)
Cc: Maoming <maoming.maoming@huawei.com>
Cc: Huangpeng (Peter) <peter.huangpeng@huawei.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Brian J. Johnson <bjohnson@sgi.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brian J. Johnson <bjohnson@sgi.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17719 6f19259b-4bc3-4df7-8a09-765794883524
Git commit 54753b60 (SVN r16870), "MdeModulePkg: Update SMBIOS revision to
3.0." changed PcdSmbiosVersion from 0x0208 to 0x0300. This controls the
version number of the SMBIOS entry point table (and other things) that
"MdeModulePkg/Universal/SmbiosDxe" installs.
Alas, this change breaks older Linux guests, like RHEL-6 (up to RHEL-6.7);
those are limited to 2.x (both in the guest kernel firmware driver, and in
the dmidecode utility). The SMBIOS 3.0 entry point has a different GUID --
defined in UEFI 2.5 -- pointing to it in the UEFI Configuration Table, and
guest kernels that lack upstream kernel commit e1ccbbc9d5 don't recognize
it.
The v2.1.0+ machine types of QEMU generate SMBIOS payload for the firmware
to install. The payload includes the entry point table ("anchor" table).
OvmfPkg/SmbiosPlatformDxe cannot install the anchor table (because that is
the jurisdiction of the generic "MdeModulePkg/Universal/SmbiosDxe"
driver); however, we can parse the entry point version from QEMU's anchor
table, and instruct "MdeModulePkg/Universal/SmbiosDxe" to adhere to that
version.
On machine types older than v2.1.0, the feature is not available, but
then, should anything in OVMF install SMBIOS tables, version 2.8 is simply
safer / more widely supported than 3.0 -- hence the default 2.8 value for
the dynamic PCD.
We set the PCD in PlatformPei (when not on the S3 resume path), because
that's an easy and certain way to set the PCD before a DXE driver reads
it. This follows the example of PcdEmuVariableNvStoreReserved (which is
read by EmuVariableFvbRuntimeDxe).
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1232876
Cc: Gabriel Somlo <somlo@cmu.edu>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Acked-by: Gabriel Somlo <somlo@cmu.edu>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17676 6f19259b-4bc3-4df7-8a09-765794883524
This patch initialises root complex register block BAR in order to
support TCO watchdog emulation features (e.g. reboot upon NO_REBOOT bit
not set) on QEMU.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17601 6f19259b-4bc3-4df7-8a09-765794883524
Make HostBridgeDevId global so MemMapInitialization() can also use it to
conditionally add RCRB MMIO address to HOB.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17600 6f19259b-4bc3-4df7-8a09-765794883524
All POWER_MGMT_REGISTER_PIIX4() macro invocations in OvmfPkg should use
the macros in "I440FxPiix4.h" as arguments.
Cc: Gabriel Somlo <somlo@cmu.edu>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Gabriel Somlo <somlo@cmu.edu>
Tested-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17435 6f19259b-4bc3-4df7-8a09-765794883524
All POWER_MGMT_REGISTER_Q35() macro invocations in OvmfPkg should use the
macros in "Q35MchIch9.h" as arguments.
Cc: Gabriel Somlo <somlo@cmu.edu>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Gabriel Somlo <somlo@cmu.edu>
Tested-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17434 6f19259b-4bc3-4df7-8a09-765794883524
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
Set from PEI, this PCD allows subsequent stages (specifically
DXE_DRIVER and DXE_RUNTIME_DRIVER) to infer the underlying platform
type (e.g. PIIX4 or Q35/MCH) without the need to further query the
Host Bridge for its Device ID.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16374 6f19259b-4bc3-4df7-8a09-765794883524
Set up ACPI power management using registers determined based on
the underlying (PIIX4 or Q35/MCH) platform type.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16373 6f19259b-4bc3-4df7-8a09-765794883524
OVMF's SecMain is unique in the sense that it links against the following
two libraries *in combination*:
- IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/
LzmaCustomDecompressLib.inf
- MdePkg/Library/BaseExtractGuidedSectionLib/
BaseExtractGuidedSectionLib.inf
The ExtractGuidedSectionLib library class allows decompressor modules to
register themselves (keyed by GUID) with it, and it allows clients to
decompress file sections with a registered decompressor module that
matches the section's GUID.
BaseExtractGuidedSectionLib is a library instance (of type BASE) for this
library class. It has no constructor function.
LzmaCustomDecompressLib is a compatible decompressor module (of type
BASE). Its section type GUID is
gLzmaCustomDecompressGuid == EE4E5898-3914-4259-9D6E-DC7BD79403CF
When OVMF's SecMain module starts, the LzmaCustomDecompressLib constructor
function is executed, which registers its LZMA decompressor with the above
GUID, by calling into BaseExtractGuidedSectionLib:
LzmaDecompressLibConstructor() [GuidedSectionExtraction.c]
ExtractGuidedSectionRegisterHandlers() [BaseExtractGuidedSectionLib.c]
GetExtractGuidedSectionHandlerInfo()
PcdGet64 (PcdGuidedExtractHandlerTableAddress) -- NOTE THIS
Later, during a normal (non-S3) boot, SecMain utilizes this decompressor
to get information about, and to decompress, sections of the OVMF firmware
image:
SecCoreStartupWithStack() [OvmfPkg/Sec/SecMain.c]
SecStartupPhase2()
FindAndReportEntryPoints()
FindPeiCoreImageBase()
DecompressMemFvs()
ExtractGuidedSectionGetInfo() [BaseExtractGuidedSectionLib.c]
ExtractGuidedSectionDecode() [BaseExtractGuidedSectionLib.c]
Notably, only the extraction depends on full-config-boot; the registration
of LzmaCustomDecompressLib occurs unconditionally in the SecMain EFI
binary, triggered by the library constructor function.
This is where the bug happens. BaseExtractGuidedSectionLib maintains the
table of GUIDed decompressors (section handlers) at a fixed memory
location; selected by PcdGuidedExtractHandlerTableAddress (declared in
MdePkg.dec). The default value of this PCD is 0x1000000 (16 MB).
This causes SecMain to corrupt guest OS memory during S3, leading to
random crashes. Compare the following two memory dumps, the first taken
right before suspending, the second taken right after resuming a RHEL-7
guest:
crash> rd -8 -p 1000000 0x50
1000000: c0 00 08 00 02 00 00 00 00 00 00 00 00 00 00 00 ................
1000010: d0 33 0c 00 00 c9 ff ff c0 10 00 01 00 88 ff ff .3..............
1000020: 0a 6d 57 32 0f 00 00 00 38 00 00 01 00 88 ff ff .mW2....8.......
1000030: 00 00 00 00 00 00 00 00 73 69 67 6e 61 6c 6d 6f ........signalmo
1000040: 64 75 6c 65 2e 73 6f 00 00 00 00 00 00 00 00 00 dule.so.........
vs.
crash> rd -8 -p 1000000 0x50
1000000: 45 47 53 49 01 00 00 00 20 00 00 01 00 00 00 00 EGSI.... .......
1000010: 20 01 00 01 00 00 00 00 a0 01 00 01 00 00 00 00 ...............
1000020: 98 58 4e ee 14 39 59 42 9d 6e dc 7b d7 94 03 cf .XN..9YB.n.{....
1000030: 00 00 00 00 00 00 00 00 73 69 67 6e 61 6c 6d 6f ........signalmo
1000040: 64 75 6c 65 2e 73 6f 00 00 00 00 00 00 00 00 00 dule.so.........
The "EGSI" signature corresponds to EXTRACT_HANDLER_INFO_SIGNATURE
declared in
MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c.
Additionally, the gLzmaCustomDecompressGuid (quoted above) is visible at
guest-phys offset 0x1000020.
Fix the problem as follows:
- Carve out 4KB from the 36KB gap that we currently have between
PcdOvmfLockBoxStorageBase + PcdOvmfLockBoxStorageSize == 8220 KB
and
PcdOvmfSecPeiTempRamBase == 8256 KB.
- Point PcdGuidedExtractHandlerTableAddress to 8220 KB (0x00807000).
- Cover the area with an EfiACPIMemoryNVS type memalloc HOB, if S3 is
supported and we're not currently resuming.
The 4KB size that we pick is an upper estimate for
BaseExtractGuidedSectionLib's internal storage size. The latter is
calculated as follows (see GetExtractGuidedSectionHandlerInfo()):
sizeof(EXTRACT_GUIDED_SECTION_HANDLER_INFO) + // 32
PcdMaximumGuidedExtractHandler * (
sizeof(GUID) + // 16
sizeof(EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + // 8
sizeof(EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER) // 8
)
OVMF sets PcdMaximumGuidedExtractHandler to 16 decimal (which is the
MdePkg default too), yielding 32 + 16 * (16 + 8 + 8) == 544 bytes.
Regarding the lifecycle of the new area:
(a) when and how it is initialized after first boot of the VM
The library linked into SecMain finds that the area lacks the signature.
It initializes the signature, plus the rest of the structure. This is
independent of S3 support.
Consumption of the area is also limited to SEC (but consumption does
depend on full-config-boot).
(b) how it is protected from memory allocations during DXE
It is not, in the general case; and we don't need to. Nothing else links
against BaseExtractGuidedSectionLib; it's OK if DXE overwrites the area.
(c) how it is protected from the OS
When S3 is enabled, we cover it with AcpiNVS in InitializeRamRegions().
When S3 is not supported, the range is not protected.
(d) how it is accessed on the S3 resume path
Examined by the library linked into SecMain. Registrations update the
table in-place (based on GUID matches).
(e) how it is accessed on the warm reset path
If S3 is enabled, then the OS won't damage the table (due to (c)), hence
see (d).
If S3 is unsupported, then the OS may or may not overwrite the
signature. (It likely will.) This is identical to the pre-patch status.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15433 6f19259b-4bc3-4df7-8a09-765794883524
If (mBootMode == BOOT_ON_S3_RESUME) -- that is, we are resuming --, then
the patch has no observable effect.
If (mBootMode != BOOT_ON_S3_RESUME && mS3Supported) -- that is, we are
booting or rebooting, and S3 is supported), then the patch has no
observable effect either.
If (mBootMode != BOOT_ON_S3_RESUME && !mS3Supported) -- that is, we are
booting or rebooting, and S3 is unsupported), then the patch effects the
following two fixes:
- The LockBox storage is reserved from DXE (but not the OS). Drivers in
DXE may save data in the LockBox regardless of S3 support, potentially
corrupting any overlapping allocations. Make sure there's no overlap.
- The LockBox storage is cleared. A LockBox inherited across a non-resume
reboot, populated with well-known GUIDs, breaks drivers that want to
save entries with those GUIDs.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Matt Fleming <matt.fleming@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15418 6f19259b-4bc3-4df7-8a09-765794883524
The S3 suspend/resume infrastructure depends on the LockBox library class.
The edk2 tree currently contains Null and SMM instances. The Null instance
is useless, and the SMM instance would require SMM emulation by including
the SMM core and adding several new drivers, which is deemed too complex.
Hence add a simple LockBoxLib instance for OVMF.
jordan.l.justen@intel.com:
* use PCDs instead of EmuNvramLib
- clear memory in PlatformPei on non S3 boots
* allocate NVS memory and store a pointer to that memory
- reduces memory use at fixed locations
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15301 6f19259b-4bc3-4df7-8a09-765794883524
On S3 resume, we skip decompression of the PEI FV, and expect
to jump directly into it. For this to work, we need the OS to
leave the memory range untouched.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15299 6f19259b-4bc3-4df7-8a09-765794883524
On X64, the reset vector code in
"OvmfPkg/ResetVector/Ia32/PageTables64.asm" identity maps the first 4GB of
RAM for PEI, consuming six frames starting at 8MB.
This range is declared by the PcdOvmfSecPageTablesBase/Size PCDs.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
[jordan.l.justen@intel.com: Move to MemDetect.c; use PCDs]
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15298 6f19259b-4bc3-4df7-8a09-765794883524
We will not be running DXE on S3 resume, so we don't
need to do these initialization items:
* Reserve EMU Variable memory range
* Declare Firmware volumes
* Add memory HOBs
v5:
* Move MiscInitialization back to running on S3 resume
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15295 6f19259b-4bc3-4df7-8a09-765794883524
This 32k section of RAM will be declared to the PEI Core on
S3 resume to allow memory allocations during S3 resume PEI.
If the boot mode is BOOT_ON_S3_RESUME, then we publish
the pre-reserved PcdS3AcpiReservedMemory range to PEI.
If the boot mode is not BOOT_ON_S3_RESUME, then we reserve
this range as ACPI NVS so the OS will not use it.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15294 6f19259b-4bc3-4df7-8a09-765794883524
QEMU indicates whether S3 is supported or not in the
fw-cfg interface.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15293 6f19259b-4bc3-4df7-8a09-765794883524
This duplicate message was intended to be removed from r15207
before it was committed. (It was pointed out by Wei Liu.)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15213 6f19259b-4bc3-4df7-8a09-765794883524
In the next commit we will update the Xen boot path
to also use this function.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15206 6f19259b-4bc3-4df7-8a09-765794883524
This will be called from a unified MemDetect function.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15203 6f19259b-4bc3-4df7-8a09-765794883524
Once we support ACPI S3, then we can restore this to
being allocated as ACPI NVS memory.
At that time we should also have a way to disable
S3 support in QEMU. When we detect that S3 is
disabled in QEMU, then we can allocate this as regular
Boot Services Data memory.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Bill Paul <wpaul@windriver.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15198 6f19259b-4bc3-4df7-8a09-765794883524
This will be needed to update the boot flow for S3 resume.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15196 6f19259b-4bc3-4df7-8a09-765794883524
The Xen and QEMU/KVM paths were calling this at nearly
the same time in the boot flow anyhow, so just make
the call in one spot.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15195 6f19259b-4bc3-4df7-8a09-765794883524
By splitting the PEI and DXE phases into separate FVs,
we can only reserve the PEI FV for ACPI S3 support.
This should save about 7MB.
Unfortunately, this all has to happen in a single commit.
DEC:
* Remove PcdOvmfMemFv(Base|Size)
* Add PcdOvmfPeiMemFv(Base|Size)
* Add PcdOvmfDxeMemFv(Base|Size)
FDF:
* Add new PEIFV. Move PEI modules here.
* Remove MAINFV
* Add PEIFV and DXEFV into FVMAIN_COMPACT
- They are added as 2 sections of a file, and compressed
together so they should retain good compression
* PcdOvmf(Pei|Dxe)MemFv(Base|Size) are set
SEC:
* Find both the PEI and DXE FVs after decompression.
- Copy them separately to their memory locations.
Platform PEI driver:
* Fv.c: Publish both FVs as appropriate
* MemDetect.c: PcdOvmfMemFv(Base|Size) =>
PcdOvmfDxeMemFv(Base|Size)
OVMF.fd before:
Non-volatile data storage
FVMAIN_COMPACT uncompressed
FV FFS file LZMA compressed
MAINFV uncompressed
individual PEI modules uncompressed
FV FFS file compressed with PI_NONE
DXEFV uncompressed
individual DXE modules uncompressed
SECFV uncompressed
OVMF.fd after:
Non-volatile data storage
FVMAIN_COMPACT uncompressed
FV FFS file LZMA compressed
PEIFV uncompressed
individual PEI modules uncompressed
DXEFV uncompressed
individual DXE modules uncompressed
SECFV uncompressed
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15151 6f19259b-4bc3-4df7-8a09-765794883524
Although SVN r14944 ("OvmfPkg: introduce PublishPeiMemory") copied a big
chunk of code from MemDetect(), calling the new PublishPeiMemory()
function in MemDetect() could not have replaced the original code in the
latter. However, with the help of the previous patch, we can do it now.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15023 6f19259b-4bc3-4df7-8a09-765794883524
This patch sets PcdPciDisableBusEnumeration to true then makes use of
PublishPeiMemory and XenMemMapInitialization to construct memory map for
Xen guest.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14946 6f19259b-4bc3-4df7-8a09-765794883524