Commit 7ea56dcc94 for qemu.org
commit 7ea56dcc9406b1588699e510439f782da7067d3e
Author: Peter Maydell <peter.maydell@linaro.org>
Date: Wed Jul 8 13:10:09 2026 +0100
hw/pci-host/q35.c: Always initialize smram-region even if SMM disabled
The MCHPCIState::smram_region looks like it ought to be SMM-specific,
but it isn't, because its behaviour is "alias the PCI address space
into system memory at the SMRAM_C_BASE offset", and it must be
enabled for "hide SMRAM", and disabled for "show SMRAM". If the
SMRAM regions are disabled, we want "hide SMRAM", so we need to
initialize and place this MR. Do this in the minimal way, by moving
the "bail out of realize if has_smm_ranges is false" check down below
the initialization code.
This fixes a bug where disabling SMM causes the VGA screen to be
blank during seabios output, until the OS graphics driver is
initialized. This is most obvious for accelerators which have no SMM
support (e.g. NVMM, HVF, WHPX) as there smm=off is the default, but
you can also see it on KVM and TCG if you explicitly pass smm=off:
qemu-system-x86_64 -machine q35,accel=kvm,smm=off
The early return is bug-prone, so we can refactor the code to clean
it up, but this is the minimal bug fix for backports, and is what
Debian used to work around this:
https://salsa.debian.org/qemu-team/qemu/-/commit/6e0766f0f897dc2b75ab87dd59da0d4639bb37ee
Another proposed fix for this:
https://patchew.org/QEMU/20260413170407.57574-1-mohamed@unpredictable.fr/
also moves an early return in mch_update-smram() and tweaks
mch_update_smram() accordingly. This shouldn't be necessary, because
in the no-SMM case smram_region should always be enabled and we don't
want to allow the guest to make it disabled.
NetBSD bug: https://gnats.NetBSD.org/59721
Cc: qemu-stable@nongnu.org
Fixes: b07bf7b7 ("q35: Introduce smm_ranges property for q35-pci-host")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/2608
Reported-by: Kroese (gitlab @kroese)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260708121011.1653365-2-peter.maydell@linaro.org>
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 4784b8f59b..47e726c41d 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -596,11 +596,14 @@ static void mch_realize(PCIDevice *d, Error **errp)
PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
}
- if (!mch->has_smm_ranges) {
- return;
- }
-
- /* if *disabled* show SMRAM to all CPUs */
+ /*
+ * This memory region looks like it's SMM specific, but it is not.
+ * It's an alias that makes the pci_address_space appear in system
+ * memory at the SMRAM_C_BASE address. The alias is enabled when the
+ * CPU should not see SMRAM, and *disabled* when the low SMRAM should be
+ * visible. So for non-SMM configs we need to create the alias, and
+ * leave it permanently enabled.
+ */
memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region",
mch->pci_address_space, MCH_HOST_BRIDGE_SMRAM_C_BASE,
MCH_HOST_BRIDGE_SMRAM_C_SIZE);
@@ -608,6 +611,10 @@ static void mch_realize(PCIDevice *d, Error **errp)
&mch->smram_region, 1);
memory_region_set_enabled(&mch->smram_region, true);
+ if (!mch->has_smm_ranges) {
+ return;
+ }
+
memory_region_init_alias(&mch->open_high_smram, OBJECT(mch), "smram-open-high",
mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE,
MCH_HOST_BRIDGE_SMRAM_C_SIZE);