hw/i386: add a separate region that tracks the SMRAME bit

This region is exported at /machine/smram.  It is "empty" if
SMRAME=0 and points to SMRAM if SMRAME=1.  The CPU will
enable/disable it as it enters or exits SMRAM.

While touching nearby code, the existing memory region setup was
slightly inconsistent.  The smram_region is *disabled* in order to open
SMRAM (because the smram_region shows the low VRAM instead of the RAM
at 0xa0000).  Because SMRAM is closed at startup, the smram_region must
be enabled when creating the i440fx or q35 devices.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2015-03-31 14:10:22 +02:00
parent 2001d0cd6d
commit fe6567d5fd
3 changed files with 32 additions and 3 deletions

View file

@ -105,6 +105,7 @@ struct PCII440FXState {
MemoryRegion *ram_memory;
PAMMemoryRegion pam_regions[13];
MemoryRegion smram_region;
MemoryRegion smram, low_smram;
uint8_t smm_enabled;
};
@ -139,6 +140,8 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
pd->config[I440FX_PAM + ((i + 1) / 2)]);
}
smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled);
memory_region_set_enabled(&d->smram,
pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME);
memory_region_transaction_commit();
}
@ -346,11 +349,23 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
f->pci_address_space);
/* if *disabled* show SMRAM to all CPUs */
memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region",
f->pci_address_space, 0xa0000, 0x20000);
memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
&f->smram_region, 1);
memory_region_set_enabled(&f->smram_region, false);
memory_region_set_enabled(&f->smram_region, true);
/* smram, as seen by SMM CPUs */
memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32);
memory_region_set_enabled(&f->smram, true);
memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low",
f->system_memory, 0xa0000, 0x20000);
memory_region_set_enabled(&f->low_smram, true);
memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram);
object_property_add_const_link(qdev_get_machine(), "smram",
OBJECT(&f->smram), &error_abort);
init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space,
&f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
for (i = 0; i < 12; ++i) {